use fyrox_core::instant;
use fyrox_graphics::framebuffer::DrawCallStatistics;
pub use fyrox_graphics::stats::*;
use std::fmt::{Display, Formatter};
use std::ops::AddAssign;
#[derive(Debug, Copy, Clone, Default)]
pub struct LightingStatistics {
pub point_lights_rendered: usize,
pub point_shadow_maps_rendered: usize,
pub csm_rendered: usize,
pub spot_lights_rendered: usize,
pub spot_shadow_maps_rendered: usize,
pub directional_lights_rendered: usize,
}
impl AddAssign for LightingStatistics {
fn add_assign(&mut self, rhs: Self) {
self.point_lights_rendered += rhs.point_lights_rendered;
self.point_shadow_maps_rendered += rhs.point_shadow_maps_rendered;
self.spot_lights_rendered += rhs.spot_lights_rendered;
self.spot_shadow_maps_rendered += rhs.spot_shadow_maps_rendered;
self.directional_lights_rendered += rhs.directional_lights_rendered;
self.csm_rendered += rhs.csm_rendered;
}
}
impl Display for LightingStatistics {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Lighting Statistics:\n\
\tPoint Lights: {}\n\
\tSpot Lights: {}\n\
\tDirectional Lights: {}\n\
\tPoint Shadow Maps: {}\n\
\tSpot Shadow Maps: {}\n\
\tSpot Shadow Maps: {}\n",
self.point_lights_rendered,
self.spot_lights_rendered,
self.directional_lights_rendered,
self.point_shadow_maps_rendered,
self.spot_shadow_maps_rendered,
self.csm_rendered
)
}
}
#[derive(Debug, Copy, Clone, Default)]
pub struct SceneStatistics {
pub pipeline: PipelineStatistics,
pub lighting: LightingStatistics,
pub geometry: RenderPassStatistics,
}
impl Display for SceneStatistics {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}\n\
{}\n\
{}\n",
self.geometry, self.lighting, self.pipeline
)
}
}
impl AddAssign<DrawCallStatistics> for SceneStatistics {
fn add_assign(&mut self, rhs: DrawCallStatistics) {
self.geometry += rhs;
}
}
impl AddAssign<PipelineStatistics> for SceneStatistics {
fn add_assign(&mut self, rhs: PipelineStatistics) {
self.pipeline += rhs;
}
}
impl AddAssign<RenderPassStatistics> for SceneStatistics {
fn add_assign(&mut self, rhs: RenderPassStatistics) {
self.geometry += rhs;
}
}
impl AddAssign<LightingStatistics> for SceneStatistics {
fn add_assign(&mut self, rhs: LightingStatistics) {
self.lighting += rhs;
}
}
#[derive(Debug, Copy, Clone)]
pub struct Statistics {
pub pipeline: PipelineStatistics,
pub lighting: LightingStatistics,
pub geometry: RenderPassStatistics,
pub pure_frame_time: f32,
pub capped_frame_time: f32,
pub frames_per_second: usize,
pub texture_cache_size: usize,
pub geometry_cache_size: usize,
pub shader_cache_size: usize,
pub uniform_buffer_cache_size: usize,
pub(super) frame_counter: usize,
pub(super) frame_start_time: instant::Instant,
pub(super) last_fps_commit_time: instant::Instant,
}
impl std::ops::AddAssign<SceneStatistics> for Statistics {
fn add_assign(&mut self, rhs: SceneStatistics) {
self.pipeline += rhs.pipeline;
self.lighting += rhs.lighting;
self.geometry += rhs.geometry;
}
}
impl Display for Statistics {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let fps = self.frames_per_second;
let pure_frame_time = self.pure_frame_time * 1000.0;
let capped_frame_time = self.capped_frame_time * 1000.0;
let geometry_stats = &self.geometry;
let lighting_stats = &self.lighting;
let pipeline_stats = &self.pipeline;
let texture_cache_size = self.texture_cache_size;
let geometry_cache_size = self.geometry_cache_size;
let shader_cache_size = self.shader_cache_size;
let uniform_buffer_cache_size = self.uniform_buffer_cache_size;
write!(
f,
"FPS: {fps}\n\
Pure Frame Time: {pure_frame_time:.2} ms\n\
Capped Frame Time: {capped_frame_time:.2} ms\n\
{geometry_stats}\n\
{lighting_stats}\n\
{pipeline_stats}\n\
Texture Cache Size: {texture_cache_size}\n\
Geometry Cache Size: {geometry_cache_size}\n\
Shader Cache Size: {shader_cache_size}\n
Uniform Buffer Cache Size: {uniform_buffer_cache_size}\n",
)
}
}
impl std::ops::AddAssign<RenderPassStatistics> for Statistics {
fn add_assign(&mut self, rhs: RenderPassStatistics) {
self.geometry += rhs;
}
}
impl Default for Statistics {
fn default() -> Self {
Self {
pipeline: Default::default(),
lighting: Default::default(),
geometry: Default::default(),
pure_frame_time: 0.0,
capped_frame_time: 0.0,
frames_per_second: 0,
texture_cache_size: 0,
geometry_cache_size: 0,
shader_cache_size: 0,
uniform_buffer_cache_size: 0,
frame_counter: 0,
frame_start_time: instant::Instant::now(),
last_fps_commit_time: instant::Instant::now(),
}
}
}
impl Statistics {
pub fn begin_frame(&mut self) {
self.frame_start_time = instant::Instant::now();
self.geometry = Default::default();
self.lighting = Default::default();
}
pub fn end_frame(&mut self) {
let current_time = instant::Instant::now();
self.pure_frame_time = current_time
.duration_since(self.frame_start_time)
.as_secs_f32();
self.frame_counter += 1;
if current_time
.duration_since(self.last_fps_commit_time)
.as_secs_f32()
>= 1.0
{
self.last_fps_commit_time = current_time;
self.frames_per_second = self.frame_counter;
self.frame_counter = 0;
}
}
pub fn finalize(&mut self) {
self.capped_frame_time = instant::Instant::now()
.duration_since(self.frame_start_time)
.as_secs_f32();
}
}