use anyhow::{Context, Result, bail};
use regex::Regex;
use crate::{Replay, ReplayOutput, replay_command};
pub struct GfxreconstructTrace {
file: String,
}
impl GfxreconstructTrace {
pub fn new(file: &str) -> GfxreconstructTrace {
GfxreconstructTrace {
file: file.to_owned(),
}
}
}
impl Replay for GfxreconstructTrace {
fn replay(&self, wrapper: Option<&str>, envs: &[(String, String)]) -> Result<ReplayOutput> {
let gfxr_command = ["gfxrecon-replay", "--swapchain", "offscreen", &self.file];
let command = replay_command(&gfxr_command, wrapper, envs);
let output: ReplayOutput = self.run_replay_command(command);
if !output.status.success() {
bail!("Failed to start gfxrecon-replay");
}
Ok(output)
}
fn fps(&self, output: &crate::ReplayOutput) -> Result<f64> {
parse_gfxrecon_fps_output(&output.stdout)
}
fn name(&self) -> &str {
&self.file
}
}
fn parse_gfxrecon_fps_output(output: &str) -> Result<f64> {
lazy_static! {
static ref CALL_RE: Regex = Regex::new("Replay FPS: ([0-9.]*) fps,").unwrap();
}
for line in output.lines() {
if let Some(cap) = CALL_RE.captures(line) {
return cap[1]
.parse::<f64>()
.with_context(|| format!("Parsing gfxrecon FPS: {}", line));
}
}
anyhow::bail!("Failed to find replay FPS line");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gfxrecon_parsing() {
let gfxrecon_input = "
[gfxrecon] INFO - Loading state for captured frame 2
[gfxrecon] INFO - Finished loading state for captured frame 2
Load time: 1.853056 seconds
Total time: 2.019838 seconds
Replay FPS: 59.958586 fps, 0.166782 seconds, 10 frames, framerange 2-11
";
assert_eq!(
parse_gfxrecon_fps_output(gfxrecon_input).unwrap(),
59.958586
);
}
}