summaryrefslogtreecommitdiff
path: root/framework
diff options
context:
space:
mode:
authorAndres Gomez <agomez@igalia.com>2020-07-29 23:24:04 +0300
committerAndres Gomez <agomez@igalia.com>2020-11-02 22:16:11 +0200
commitfaed7620ec69a63af78a5c7cb097b80ba0fe8e85 (patch)
treeb537d0894bb73c56b6cbc21b9490e39e3205ad33 /framework
parentbda3ad0a3bf7ec50a3dacff4a6368907def8ebd6 (diff)
framework/replay: add programs module
v2: - Updated the README.md - Improved the documentation of the calls parameter for the dump command. - Added missing parameter in the dump program inner call. v3: - Make it compatible with python 3.6. v4: - Directly return the inner function return value in the compare program. v5: - Remove extra empty line (Dylan). Signed-off-by: Andres Gomez <agomez@igalia.com> Reviewed-by: Dylan Baker <dylan@pnwbakers.com> Part-of: <https://gitlab.freedesktop.org/mesa/piglit/-/merge_requests/353>
Diffstat (limited to 'framework')
-rw-r--r--framework/replay/README.md200
-rw-r--r--framework/replay/programs/__init__.py0
-rw-r--r--framework/replay/programs/checksum.py (renamed from framework/replay/parsers.py)41
-rw-r--r--framework/replay/programs/compare.py108
-rw-r--r--framework/replay/programs/download.py58
-rw-r--r--framework/replay/programs/dump.py74
-rw-r--r--framework/replay/programs/parsers.py85
-rw-r--r--framework/replay/programs/query.py119
8 files changed, 568 insertions, 117 deletions
diff --git a/framework/replay/README.md b/framework/replay/README.md
index f8d3cfaa2..9028fb80a 100644
--- a/framework/replay/README.md
+++ b/framework/replay/README.md
@@ -1,7 +1,5 @@
-Tracie - Mesa Traces Continuous Integration System
-==================================================
-
-Home of the Mesa trace testing effort.
+Replayer
+========
### Traces definition file
@@ -27,140 +25,142 @@ traces:
```
The `traces-db` entry can be absent, in which case it is assumed that
-the traces can be found in the `CWD/traces-db` directory.
+the traces can be found in the `CWD/replayer-db` directory.
Traces that don't have an expectation for the current device are skipped
during trace replay.
-Adding a new trace to the list involves commiting the trace to the git repo and
-adding an entry to the `traces` list. The reference checksums can be calculated
-with the [image_checksum.py](.gitlab-ci/tracie/image_checksum.py) script.
-Alternatively, an arbitrary checksum can be used, and during replay (see below)
-the scripts will report the mismatch and expected checksum.
+Adding a new trace to the list involves uploading the trace to the
+remote `traces-db` and adding an entry to the `traces` list. The
+reference checksums can be calculated with the `checksum` command.
+Alternatively, an arbitrary checksum can be used, and during replay
+(see below) the scripts will report the mismatch and expected
+checksum.
### Trace-db download urls
The trace-db:download-url property contains an HTTPS url from which traces can
be downloaded, by appending traces:path properties to it.
-### Enabling trace testing on a new device
-
-To enable trace testing on a new device:
-
-1. Create a new job in .gitlab-ci.yml. The job will need to be tagged
- to run on runners with the appropriate hardware.
-
- 1. If you mean to test GL traces, use the `.traces-test-gl`
- template jobs as a base, and make sure you set a unique value for the
- `DEVICE_NAME` variable:
-
- ```yaml
- my-hardware-gl-traces:
- extends: .traces-test-gl
- variables:
- DEVICE_NAME: "gl-myhardware"
- ```
-
- 2. If you mean to test Vulkan traces, use the `.traces-test-vk`
- template jobs as a base, set the `VK_DRIVER` variable, and make
- sure you set a unique value for the `DEVICE_NAME` variable:
-
- ```yaml
- my-hardware-vk-traces:
- extends: .traces-test-vk
- variables:
- VK_DRIVER: "radeon"
- DEVICE_NAME: "vk-myhardware"
- ```
-
-2. Update the .gitlab-ci/traces.yml file with expectations for the new device.
- Ensure that the device name used in the expectations matches the one
- set in the job. For more information, and tips about how to calculate
- the checksums, see the section describing the trace definition files.
-
### Trace files
-Tracie supports renderdoc (.rdc), apitrace (.trace) and gfxreconstruct
-(.gfxr) files. Trace files need to have the correct extension so that
-tracie can detect them properly.
+replayer supports renderdoc (.rdc), apitrace (.trace, .trace-dxgi) and
+gfxreconstruct (.gfxr) files. Trace files need to have the correct
+extension so that replayer can detect them properly.
-The trace files that are contained in public traces-db repositories must be
-legally redistributable. This is typically true for FOSS games and
-applications. Traces for proprietary games and application are typically not
-redistributable, unless specific redistribution rights have been granted by the
-publisher.
+The trace files that are contained in public `traces-db` stores must
+be legally redistributable. This is typically true for FOSS games and
+applications. Traces for proprietary games and application are
+typically not redistributable, unless specific redistribution rights
+have been granted by the publisher.
-Trace files in a given repository are expected to be immutable once committed
-for the first time, so any changes need to be accompanied by a change in the
-file name (eg. by appending a _v2 suffix to the file).
+In order to have reliable comparisons, trace files in a given store
+are expected to be immutable. Any change to a trace file means that it
+needs to be renamed and updated in the traces definition file (eg. by
+appending a _v2 suffix to the file).
### Replaying traces
-Mesa traces CI uses a set of scripts to replay traces and check the output
-against reference checksums.
+replayer features a series of commands to deal with traces:
+ * `checksum`: will calculate the checksum for a given image file.
+ * `compare`: will download a trace or all the traces in a traces
+ definition file for a given device, replay them and compare their
+ checksum against the expected ones.
+ * `download`: will download a file, given a relative path, from a
+ remote url.
+ * `dump`: will dump as images the last call or specified calls from a
+ trace file, given a specific device.
+ * `query`: will return the queried information from a given traces
+ definition file.
+
+You can get a more complete help running:
-The high level script [tracie.py](.gitlab-ci/tracie/tracie.py) accepts
-commands to use a `yaml` traces definition file, `query` for data from
-a traces definition file, or the description of an individual `trace`:
+ ```sh
+ $ replayer.py <command> --help
+ ```
Examples:
```sh
- $ tracie.py yaml \
- --device-name gl-vmware-llvmpipe \
- --file .gitlab-ci/traces.yml
+ $ replayer.py checksum ./vkcube.gfxr-9.png
```
```sh
- $ tracie.py query \
- --file .gitlab-ci/traces.yml \
- traces \
- --device-name gl-vmware-llvmpipe \
- --trace-types apitrace,renderdoc \
- --checksum
+ $ replayer.py compare trace \
+ --output ./results \
+ --device-name gl-vmware-llvmpipe \
+ --download-url https://minio-packet.freedesktop.org/mesa-tracie-public/ \
+ glmark2/desktop-blur-radius=5:effect=blur:passes=1:separable=true:windows=4.rdc \
+ 8867f3a41f180626d0d4b7661ff5c0f4
```
```sh
- $ tracie.py trace \
- --device-name gl-vmware-llvmpipe \
- --download-url https://minio-packet.freedesktop.org/mesa-tracie-public/ \
- --path glmark2/jellyfish.rdc \
- --expected-checksum d82267c25a0decdad7b563c56bb81106
+ $ replayer.py compare yaml \
+ --yaml-file ./traces.yml \
+ --device-name gl-vmware-llvmpipe \
+ --keep-image
```
-tracie.py copies the produced artifacts to the `$CI_PROJECT_DIR/result`
-directory. By default, created images from traces are only stored in case of a
-checksum mismatch. The `TRACIE_STORE_IMAGES` CI/environment variable can be set
-to `1` to force storing images, e.g., to get a complete set of reference
-images.
-
-At a lower level the
-[dump_trace_images.py](.gitlab-ci/tracie/dump_trace_images.py) script is
-called, which replays a trace, dumping a set of images in the process. By
-default only the image corresponding to the last frame of the trace is dumped,
-but this can be changed with the `--calls` parameter. The dumped images are
-stored in a subdirectory `test/<device-name>` next to the trace file itself,
-with names of the form `tracefilename-callnum.png`. The full log of any
-commands used while dumping the images is also saved in a file in the
-'test/<device-name>' subdirectory, named after the trace name with '.log'
-appended.
+ ```sh
+ $ replayer.py download \
+ --download-url https://minio-packet.freedesktop.org/mesa-tracie-public/ \
+ --db-path ./traces-db \
+ --force-download \
+ glmark2/desktop-blur-radius=5:effect=blur:passes=1:separable=true:windows=4.rdc
+ ```
-Examples:
+ ```sh
+ $ replayer.py dump \
+ --config ./piglit.conf \
+ --output ./results \
+ --device-name gl-vmware-llvmpipe \
+ --calls "3,8,9" \
+ glmark2/desktop-blur-radius=5:effect=blur:passes=1:separable=true:windows=4.rdc
+ ```
+
+ ```sh
+ $ replayer.py query \
+ --yaml-file ./traces.yml \
+ checksum \
+ --device-name gl-vmware-llvmpipe \
+ glmark2/desktop-blur-radius=5:effect=blur:passes=1:separable=true:windows=4.rdc
+ ```
```sh
- $ python3 dump_traces_images.py --device-name=gl-vmware-llvmpipe mytrace.trace
+ $ replayer.py query \
+ --yaml-file ./traces.yml \
+ traces \
+ --device-name gl-vmware-llvmpipe \
+ --trace-types "apitrace,renderdoc"
+ --checksum
```
```sh
- $ python3 dump_traces_images.py --device-name=gl-vmware-llvmpipe --calls=2075,3300 mytrace.trace
+ $ replayer.py query \
+ --yaml-file ./traces.yml \
+ traces_db_download_url
```
-### Running the replay scripts locally
+Unless specified when comparing or dumping, replayer places the
+produced artifacts at the `CWD/results` directory. By default, created
+images from traces are only stored in case of a checksum
+mismatch. This can be overriden with the `--keep-image` parameter to
+force storing images, e.g., to get a complete set of reference images.
+
+By default when dumping, only the image corresponding to the last frame
+of the trace is created. This can be changed with the `--calls`
+parameter.
+
+Unless specified with the `--output` parameter, the dumped images are
+stored in the subdirectory `./test/<device-name>/<trace_file_path/` ,
+with names of the form `trace_file_name-call_num.png`. The full log
+of any commands used while dumping the images is also saved in a file
+in the 'test/<device-name>' subdirectory, named after the trace name
+with '.log' appended.
-It's often useful, especially during development, to be able to run the scripts
-locally.
+### Specific dependencies for dumping depending of the trace type
-Depending on the target 3D API, the scripts require a recent version
+Depending on the target 3D API, replayer requires a recent version
of apitrace (and eglretrace) being in the path, and also the renderdoc
python module being available, for GL traces.
@@ -170,7 +170,7 @@ and `LD_LIBRARY_PATH` to point to the location of `librenderdoc.so`. In the
renderdoc build tree, both of these are in `renderdoc/<builddir>/lib`. Note
that renderdoc doesn't install the `renderdoc.so` python module.
-In the case of Vulkan traces, the scripts need a recent version of
+In the case of Vulkan traces, replayer needs a recent version of
gfxrecon-info and gfxrecon-replay being in the path, and also the
`VK_LAYER_LUNARG_screenshot` Vulkan layer from LunarG's VulkanTools.
@@ -179,7 +179,7 @@ to set `VK_LAYER_PATH` to point to the location of
`VkLayer_screenshot.json` and `LD_LIBRARY_PATH` to point to the
location of `libVkLayer_screenshot.so`.
-In the case of DXGI traces, the scripts require Wine, a recent version
+In the case of DXGI traces, replayer requires Wine, a recent version
of DXVK installed in the default `WINEPREFIX`, and a recent binary
version of apitrace (and d3dretrace) for Windows which should be
reachable through Windows' `PATH` environment variable.
diff --git a/framework/replay/programs/__init__.py b/framework/replay/programs/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/framework/replay/programs/__init__.py
diff --git a/framework/replay/parsers.py b/framework/replay/programs/checksum.py
index 8d0c2531a..81e08f690 100644
--- a/framework/replay/parsers.py
+++ b/framework/replay/programs/checksum.py
@@ -1,6 +1,5 @@
# coding=utf-8
#
-# Copyright (c) 2015-2016, 2019 Intel Corporation
# Copyright © 2020 Valve Corporation.
#
# Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,20 +24,28 @@
import argparse
+from framework import exceptions
+from framework.replay import image_checksum
-DEVICE = argparse.ArgumentParser(add_help=False)
-DEVICE.add_argument(
- '-d', '--device-name',
- dest="device_name",
- required=False,
- default="",
- help='the name of the graphics device used to replay traces')
-
-YAML = argparse.ArgumentParser(add_help=False)
-YAML.add_argument(
- '-f', '--file',
- dest="yaml_file",
- required=True,
- type=argparse.FileType("r"),
- help=('the name of the traces.yml file listing traces '
- 'and their checksums for each device'))
+
+__all__ = ['checksum']
+
+
+def _hexdigest_from_image(args):
+ print(image_checksum.hexdigest_from_image(args.file_path))
+
+
+@exceptions.handler
+def checksum(input_):
+ """ Parser for replayer checksum command """
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument(
+ 'file_path',
+ help=('the path to the image file '
+ 'from which to calculate its checksum'))
+ parser.set_defaults(func=_hexdigest_from_image)
+
+ args = parser.parse_args(input_)
+
+ args.func(args)
diff --git a/framework/replay/programs/compare.py b/framework/replay/programs/compare.py
new file mode 100644
index 000000000..6647422a7
--- /dev/null
+++ b/framework/replay/programs/compare.py
@@ -0,0 +1,108 @@
+# coding=utf-8
+#
+# Copyright © 2020 Valve 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.
+#
+# SPDX-License-Identifier: MIT
+
+import argparse
+
+from framework import exceptions
+from framework.replay import compare_replay
+from framework.replay import options
+from framework.programs import parsers as piglit_parsers
+from . import parsers
+
+
+__all__ = ['compare']
+
+
+def _from_yaml(args):
+ options.OPTIONS.device_name = args.device_name
+ options.OPTIONS.keep_image = args.keep_image
+ options.OPTIONS.download['force'] = args.force_download
+ options.OPTIONS.db_path = args.db_path
+ options.OPTIONS.results_path = args.output
+
+ return compare_replay.from_yaml(args.yaml_file)
+
+
+def _trace(args):
+ options.OPTIONS.device_name = args.device_name
+ options.OPTIONS.keep_image = args.keep_image
+ options.OPTIONS.set_download_url(args.download_url)
+ options.OPTIONS.download['force'] = args.force_download
+ options.OPTIONS.db_path = args.db_path
+ options.OPTIONS.results_path = args.output
+
+ return compare_replay.trace(args.file_path, args.expected_checksum)
+
+
+@exceptions.handler
+def compare(input_):
+ """ Parser for replayer compare command """
+ unparsed = piglit_parsers.parse_config(input_)[1]
+
+ try:
+ # Set the parent of the config to add the -f/--config message
+ parser = argparse.ArgumentParser(parents=[piglit_parsers.CONFIG])
+ # The "required" keyword is only available since python >= 3.7
+ subparsers = parser.add_subparsers(dest='command', required=True)
+ except TypeError:
+ parser = argparse.ArgumentParser(parents=[piglit_parsers.CONFIG])
+ # Add a destination due to
+ # https://github.com/python/cpython/pull/3027#issuecomment-330910633
+ subparsers = parser.add_subparsers(dest='command')
+
+ parser_trace = subparsers.add_parser(
+ 'trace',
+ parents=[parsers.DEVICE,
+ parsers.KEEP_IMAGE,
+ parsers.DOWNLOAD_URL,
+ parsers.DOWNLOAD_FORCE,
+ parsers.DB_PATH,
+ parsers.RESULTS_PATH],
+ help=('Compares a specific trace given a checksum and a device.'))
+ parser_trace.add_argument(
+ 'file_path',
+ help=('the relative path to the trace file inside the db path. '
+ 'If not present and given that an URL has been provided '
+ 'for its download, the relative path to the file in such URL.'))
+ parser_trace.add_argument(
+ 'expected_checksum',
+ help=('the expected checksum value to obtain '
+ 'when replaying a trace in a specific device'))
+ parser_trace.set_defaults(func=_trace)
+
+ parser_yaml = subparsers.add_parser(
+ 'yaml',
+ parents=[parsers.DEVICE,
+ parsers.KEEP_IMAGE,
+ parsers.YAML,
+ parsers.DOWNLOAD_FORCE,
+ parsers.DB_PATH,
+ parsers.RESULTS_PATH],
+ help=('Compares from a traces description file listing traces '
+ 'and their checksums for a given device.'))
+ parser_yaml.set_defaults(func=_from_yaml)
+
+ args = parser.parse_args(unparsed)
+
+ return args.func(args)
diff --git a/framework/replay/programs/download.py b/framework/replay/programs/download.py
new file mode 100644
index 000000000..2a7311d81
--- /dev/null
+++ b/framework/replay/programs/download.py
@@ -0,0 +1,58 @@
+# coding=utf-8
+#
+# Copyright © 2020 Valve 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.
+#
+# SPDX-License-Identifier: MIT
+
+import argparse
+
+from framework import exceptions
+from framework.replay import download_utils
+from framework.replay import options
+from . import parsers
+
+
+__all__ = ['download']
+
+
+def _ensure_file(args):
+ options.OPTIONS.set_download_url(args.download_url)
+ options.OPTIONS.download['force'] = args.force_download
+ options.OPTIONS.db_path = args.db_path
+
+ return download_utils.ensure_file(args.file_path)
+
+
+@exceptions.handler
+def download(input_):
+ """ Parser for replayer download command """
+ parser = argparse.ArgumentParser(parents=[parsers.DOWNLOAD_URL,
+ parsers.DOWNLOAD_FORCE,
+ parsers.DB_PATH])
+ parser.add_argument(
+ 'file_path',
+ help=('the path to the file '
+ 'at the provided URL from which to download'))
+ parser.set_defaults(func=_ensure_file)
+
+ args = parser.parse_args(input_)
+
+ args.func(args)
diff --git a/framework/replay/programs/dump.py b/framework/replay/programs/dump.py
new file mode 100644
index 000000000..7a52ea0ac
--- /dev/null
+++ b/framework/replay/programs/dump.py
@@ -0,0 +1,74 @@
+# coding=utf-8
+#
+# Copyright © 2020 Valve 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.
+#
+# SPDX-License-Identifier: MIT
+
+import argparse
+
+from framework import exceptions
+from framework.replay import dump_trace_images
+from framework.replay import options
+from framework.programs import parsers as piglit_parsers
+from . import parsers
+
+
+__all__ = ['dump']
+
+
+def _dump_from_trace(args):
+ options.OPTIONS.device_name = args.device_name
+ options.OPTIONS.results_path = args.output
+
+ if args.calls is not None:
+ calls = args.calls.split(",")
+ else:
+ calls = []
+
+ return dump_trace_images.dump_from_trace(args.file_path, args.output,
+ calls)
+
+
+@exceptions.handler
+def dump(input_):
+ """ Parser for replayer dump command """
+ unparsed = piglit_parsers.parse_config(input_)[1]
+
+ # Set the parent of the config to add the -f/--config message
+ parser = argparse.ArgumentParser(parents=[piglit_parsers.CONFIG,
+ parsers.DEVICE,
+ parsers.RESULTS_PATH])
+ parser.add_argument(
+ '-c', '--calls',
+ dest='calls',
+ required=False,
+ default=None,
+ help=('a comma separated list of call numbers from the trace to dump '
+ '(default: last frame).'))
+ parser.add_argument(
+ 'file_path',
+ help=('the path to the local trace file '
+ 'from which to dump images.'))
+ parser.set_defaults(func=_dump_from_trace)
+
+ args = parser.parse_args(unparsed)
+
+ return 0 if args.func(args) else 1
diff --git a/framework/replay/programs/parsers.py b/framework/replay/programs/parsers.py
new file mode 100644
index 000000000..70ada2147
--- /dev/null
+++ b/framework/replay/programs/parsers.py
@@ -0,0 +1,85 @@
+# coding=utf-8
+#
+# Copyright (c) 2015-2016, 2019 Intel Corporation
+# Copyright © 2020 Valve 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.
+#
+# SPDX-License-Identifier: MIT
+
+import argparse
+
+
+DEVICE = argparse.ArgumentParser(add_help=False)
+DEVICE.add_argument(
+ '-d', '--device-name',
+ dest='device_name',
+ required=False,
+ default=None,
+ help='the name of the graphics device used to replay traces')
+
+KEEP_IMAGE = argparse.ArgumentParser(add_help=False)
+KEEP_IMAGE.add_argument(
+ '-k', '--keep-image',
+ dest='keep_image',
+ action='store_true',
+ help=('forces keeping the image generated '
+ 'for the comparison.'))
+
+YAML = argparse.ArgumentParser(add_help=False)
+YAML.add_argument(
+ '-y', '--yaml-file',
+ dest='yaml_file',
+ required=True,
+ type=argparse.FileType('r'),
+ help=('the name of the traces YAML description file listing traces '
+ 'and their checksums for each device'))
+
+DOWNLOAD_URL = argparse.ArgumentParser(add_help=False)
+DOWNLOAD_URL.add_argument(
+ '-u', '--download-url',
+ dest='download_url',
+ required=False,
+ default=None,
+ help=('the URL from which to download the files'))
+
+DOWNLOAD_FORCE = argparse.ArgumentParser(add_help=False)
+DOWNLOAD_FORCE.add_argument(
+ '-w', '--force-download',
+ dest='force_download',
+ action='store_true',
+ help=('forces downloading '
+ 'even if the destination file already exists'))
+
+DB_PATH = argparse.ArgumentParser(add_help=False)
+DB_PATH.add_argument(
+ '-p', '--db-path',
+ dest='db_path',
+ required=False,
+ default='./replayer-db/',
+ help=('the path to the objects db or where it will be created. '
+ 'Defaults to "./replayer-db/".'))
+
+RESULTS_PATH = argparse.ArgumentParser(add_help=False)
+RESULTS_PATH.add_argument(
+ '-o', '--output',
+ dest='output',
+ required=False,
+ default='./results/',
+ help=('the path in which to place the results. Defaults to "./results/"'))
diff --git a/framework/replay/programs/query.py b/framework/replay/programs/query.py
new file mode 100644
index 000000000..ba9b40585
--- /dev/null
+++ b/framework/replay/programs/query.py
@@ -0,0 +1,119 @@
+# coding=utf-8
+#
+# Copyright (c) 2019 Collabora Ltd
+# Copyright © 2020 Valve 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.
+#
+# SPDX-License-Identifier: MIT
+
+import argparse
+
+from framework import exceptions
+from framework.replay import query_traces_yaml as qty
+from . import parsers
+
+
+__all__ = ['query']
+
+
+def _traces_db_download_url(args):
+ y = qty.load_yaml(args.yaml_file)
+
+ url = qty.download_url(y) or ""
+
+ print(url)
+
+
+def _traces(args):
+ y = qty.load_yaml(args.yaml_file)
+
+ t_list = qty.traces(y,
+ trace_types=args.trace_types,
+ device_name=args.device_name,
+ checksum=args.checksum)
+
+ if args.checksum:
+ print('\n'.join(((t['path'] + '\n' + t['checksum'])
+ for t in t_list)))
+ else:
+ print('\n'.join((t['path'] for t in t_list)))
+
+
+def _checksum(args):
+ y = qty.load_yaml(args.yaml_file)
+
+ traces = y['traces']
+ try:
+ trace = next(t for t in traces if t['path'] == args.file_path)
+ except StopIteration:
+ print("")
+ return
+
+ print(qty.trace_checksum(trace, args.device_name))
+
+
+@exceptions.handler
+def query(input_):
+ """ Parser for replayer query command """
+ try:
+ parser = argparse.ArgumentParser(parents=[parsers.YAML])
+ # The "required" keyword is only available since python >= 3.7
+ subparsers = parser.add_subparsers(dest='command', required=True)
+ except TypeError:
+ parser = argparse.ArgumentParser(parents=[parsers.YAML])
+ # Add a destination due to
+ # https://github.com/python/cpython/pull/3027#issuecomment-330910633
+ subparsers = parser.add_subparsers(dest='command')
+
+ parser_checksum = subparsers.add_parser(
+ 'checksum',
+ parents=[parsers.DEVICE],
+ help=('Outputs, if available, the checksum that a specific device '
+ 'should produce for a specified trace file.'))
+ parser_checksum.add_argument(
+ 'file_path',
+ help=('the path to a trace file.'))
+ parser_checksum.set_defaults(func=_checksum)
+
+ parser_traces = subparsers.add_parser(
+ 'traces',
+ parents=[parsers.DEVICE],
+ help=('Outputs the trace files filtered by the optional arguments.'))
+ parser_traces.add_argument(
+ '-t', '--trace-types',
+ required=False,
+ default=None,
+ help=('a comma separated list of trace types to look for '
+ 'in recursive dir walks. '
+ 'If none are provide, all types are used by default'))
+ parser_traces.add_argument(
+ '-c', '--checksum',
+ action='store_true',
+ help='whether to print the checksum below every trace')
+ parser_traces.set_defaults(func=_traces)
+
+ parser_traces_db_download_url = subparsers.add_parser(
+ 'traces_db_download_url',
+ help=('Outputs, if available, the download URL.'))
+ parser_traces_db_download_url.set_defaults(func=_traces_db_download_url)
+
+ args = parser.parse_args(input_)
+
+ args.func(args)