#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum RuntimeMode {
#[default]
Interactive,
Playback,
Paused,
Capture,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum QualityPreset {
High,
Medium,
Low,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PerformancePolicy {
pub preset: Option<QualityPreset>,
pub target_fps: Option<f32>,
pub min_render_scale: f32,
pub max_render_scale: f32,
pub allow_dynamic_resolution: bool,
pub allow_shadow_reduction: bool,
pub allow_volume_quality_reduction: bool,
pub allow_effect_throttling: bool,
}
impl Default for PerformancePolicy {
fn default() -> Self {
Self {
preset: None,
target_fps: None,
min_render_scale: 0.5,
max_render_scale: 1.0,
allow_dynamic_resolution: false,
allow_shadow_reduction: false,
allow_volume_quality_reduction: false,
allow_effect_throttling: false,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct FrameStats {
pub total_objects: u32,
pub visible_objects: u32,
pub culled_objects: u32,
pub draw_calls: u32,
pub instanced_batches: u32,
pub triangles_submitted: u64,
pub shadow_draw_calls: u32,
pub cpu_prepare_ms: f32,
pub gpu_frame_ms: Option<f32>,
pub total_frame_ms: f32,
pub render_scale: f32,
pub missed_budget: bool,
pub upload_bytes: u64,
pub gpu_culling_active: bool,
pub gpu_visible_instances: Option<u32>,
pub shadows_skipped: bool,
pub volume_quality_reduced: bool,
pub effects_throttled: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_frame_stats_default_is_zero() {
let stats = FrameStats::default();
assert_eq!(stats.total_objects, 0);
assert_eq!(stats.visible_objects, 0);
assert_eq!(stats.culled_objects, 0);
assert_eq!(stats.draw_calls, 0);
assert_eq!(stats.instanced_batches, 0);
assert_eq!(stats.triangles_submitted, 0);
assert_eq!(stats.shadow_draw_calls, 0);
assert_eq!(stats.cpu_prepare_ms, 0.0);
assert!(stats.gpu_frame_ms.is_none());
assert_eq!(stats.total_frame_ms, 0.0);
assert_eq!(stats.render_scale, 0.0);
assert!(!stats.missed_budget);
assert_eq!(stats.upload_bytes, 0);
assert!(!stats.gpu_culling_active);
assert!(stats.gpu_visible_instances.is_none());
assert!(!stats.shadows_skipped);
assert!(!stats.volume_quality_reduced);
assert!(!stats.effects_throttled);
}
#[test]
fn test_runtime_mode_default_is_interactive() {
assert_eq!(RuntimeMode::default(), RuntimeMode::Interactive);
}
#[test]
fn test_performance_policy_default() {
let p = PerformancePolicy::default();
assert!(p.preset.is_none());
assert!(p.target_fps.is_none());
assert!(!p.allow_dynamic_resolution);
assert!(p.min_render_scale <= p.max_render_scale);
assert_eq!(p.max_render_scale, 1.0);
}
}