bevy_render/diagnostic/
render_asset_diagnostic_plugin.rs

1use core::{any::type_name, marker::PhantomData};
2
3use bevy_app::{Plugin, PreUpdate};
4use bevy_diagnostic::{Diagnostic, DiagnosticPath, Diagnostics, RegisterDiagnostic};
5use bevy_ecs::{resource::Resource, system::Res};
6use bevy_platform::sync::atomic::{AtomicUsize, Ordering};
7
8use crate::{
9    render_asset::{RenderAsset, RenderAssets},
10    Extract, ExtractSchedule, RenderApp,
11};
12
13pub struct RenderAssetDiagnosticPlugin<A: RenderAsset> {
14    suffix: &'static str,
15    _phantom: PhantomData<A>,
16}
17
18impl<A: RenderAsset> RenderAssetDiagnosticPlugin<A> {
19    pub fn new(suffix: &'static str) -> Self {
20        Self {
21            suffix,
22            _phantom: PhantomData,
23        }
24    }
25
26    pub fn render_asset_diagnostic_path() -> DiagnosticPath {
27        DiagnosticPath::from_components(["render_asset", type_name::<A>()])
28    }
29}
30
31impl<A: RenderAsset> Plugin for RenderAssetDiagnosticPlugin<A> {
32    fn build(&self, app: &mut bevy_app::App) {
33        app.register_diagnostic(
34            Diagnostic::new(Self::render_asset_diagnostic_path()).with_suffix(self.suffix),
35        )
36        .init_resource::<RenderAssetMeasurements<A>>()
37        .add_systems(PreUpdate, add_render_asset_measurement::<A>);
38
39        if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
40            render_app.add_systems(ExtractSchedule, measure_render_asset::<A>);
41        }
42    }
43}
44
45#[derive(Debug, Resource)]
46struct RenderAssetMeasurements<A: RenderAsset> {
47    assets: AtomicUsize,
48    _phantom: PhantomData<A>,
49}
50
51impl<A: RenderAsset> Default for RenderAssetMeasurements<A> {
52    fn default() -> Self {
53        Self {
54            assets: AtomicUsize::default(),
55            _phantom: PhantomData,
56        }
57    }
58}
59
60fn add_render_asset_measurement<A: RenderAsset>(
61    mut diagnostics: Diagnostics,
62    measurements: Res<RenderAssetMeasurements<A>>,
63) {
64    diagnostics.add_measurement(
65        &RenderAssetDiagnosticPlugin::<A>::render_asset_diagnostic_path(),
66        || measurements.assets.load(Ordering::Relaxed) as f64,
67    );
68}
69
70fn measure_render_asset<A: RenderAsset>(
71    measurements: Extract<Res<RenderAssetMeasurements<A>>>,
72    assets: Res<RenderAssets<A>>,
73) {
74    measurements
75        .assets
76        .store(assets.iter().count(), Ordering::Relaxed);
77}