gpu_trace_perf/
traces_config.rs1use std::{collections::HashMap, path::Path};
4
5use anyhow::{Context, Result};
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Deserialize, Serialize)]
9#[serde(deny_unknown_fields)]
10pub struct TracesConfig {
11 pub traces_db: TracesDb,
12 pub traces: Vec<TraceEntry>,
13}
14
15impl TracesConfig {
16 pub fn load(path: &Path) -> Result<TracesConfig> {
17 let contents = std::fs::read_to_string(path)
18 .with_context(|| format!("reading config file {}", path.display()))?;
19 toml::from_str(&contents).with_context(|| format!("parsing TOML config {}", path.display()))
20 }
21}
22
23#[derive(Debug, Deserialize, Serialize)]
24#[serde(deny_unknown_fields)]
25pub struct TracesDb {
26 pub download_url: String,
27}
28
29#[derive(Debug, Deserialize, Serialize)]
30#[serde(deny_unknown_fields)]
31pub struct TraceEntry {
32 pub path: String,
33 #[serde(default)]
38 pub nonloopable: bool,
39 #[serde(default)]
42 pub replay_args: Vec<String>,
43 #[serde(default)]
44 pub devices: HashMap<String, DeviceEntry>,
45}
46
47impl TraceEntry {
48 pub fn device(&self, name: &str) -> Option<&DeviceEntry> {
49 self.devices.get(name)
50 }
51}
52
53#[derive(Debug, Deserialize, Serialize)]
54#[serde(deny_unknown_fields)]
55pub struct DeviceEntry {
56 pub checksum: String,
57 #[serde(default)]
59 pub singlethread: bool,
60 #[serde(default)]
62 pub skip: bool,
63 #[serde(default)]
66 pub replay_args: Vec<String>,
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 const MINIMAL_TOML: &str = r#"
74[traces_db]
75download_url = "https://s3.freedesktop.org/mesa-tracie-public/"
76
77[[traces]]
78path = "valve/half-life-2-v2.trace"
79devices = {
80 freedreno-a306 = {
81 checksum = "8f5929c82e7d990e8c3d2bea14688224aabbccdd8f5929c82e7d990e8c3d2bea",
82 skip = true,
83 },
84 freedreno-a530 = {
85 checksum = "c7b816feafeae42eef3ccd5357db4cd7c7b816feafeae42eef3ccd5357db4cd7",
86 },
87}
88
89[[traces]]
90path = "valve/portal-2-v2.trace"
91devices = {
92 freedreno-a530 = {
93 checksum = "102a09ce76092436173fd09a6a2bd941102a09ce76092436173fd09a6a2bd941"
94 },
95}
96"#;
97
98 #[test]
99 fn parse_minimal_toml() {
100 let config: TracesConfig = toml::from_str(MINIMAL_TOML).expect("parsing TOML");
101
102 assert_eq!(
103 config.traces_db.download_url,
104 "https://s3.freedesktop.org/mesa-tracie-public/"
105 );
106 assert_eq!(config.traces.len(), 2);
107
108 let hl2 = &config.traces[0];
109 assert_eq!(hl2.path, "valve/half-life-2-v2.trace");
110 assert_eq!(hl2.devices.len(), 2);
111
112 let a306 = &hl2.device("freedreno-a306").unwrap();
113 assert_eq!(
114 a306.checksum,
115 "8f5929c82e7d990e8c3d2bea14688224aabbccdd8f5929c82e7d990e8c3d2bea"
116 );
117 assert!(a306.skip);
118
119 let a530 = &hl2.device("freedreno-a530").unwrap();
120 assert!(!a530.skip);
121 }
122
123 #[test]
124 fn device_lookup() {
125 let config: TracesConfig = toml::from_str(MINIMAL_TOML).expect("parsing TOML");
126 let hl2 = &config.traces[0];
127
128 assert!(hl2.device("freedreno-a306").is_some());
129 assert!(hl2.device("freedreno-a530").is_some());
130 assert!(hl2.device("unknown-device").is_none());
131 }
132
133 #[test]
134 fn skip_detection() {
135 let config: TracesConfig = toml::from_str(MINIMAL_TOML).expect("parsing TOML");
136 let hl2 = &config.traces[0];
137
138 let a306 = hl2.device("freedreno-a306").unwrap();
139 assert!(a306.skip);
140
141 let a530 = hl2.device("freedreno-a530").unwrap();
142 assert!(!a530.skip);
143 }
144
145 #[test]
146 fn trace_with_no_device_entry() {
147 let config: TracesConfig = toml::from_str(MINIMAL_TOML).expect("parsing TOML");
148 let portal2 = &config.traces[1];
149
150 assert_eq!(portal2.path, "valve/portal-2-v2.trace");
151 assert!(portal2.device("freedreno-a306").is_none());
152 assert!(portal2.device("freedreno-a530").is_some());
153 }
154}