Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_pbr/src/diagnostic.rs
7219 views
1
use core::{
2
any::{type_name, Any, TypeId},
3
marker::PhantomData,
4
};
5
6
use bevy_app::{Plugin, PreUpdate};
7
use bevy_diagnostic::{Diagnostic, DiagnosticPath, Diagnostics, RegisterDiagnostic};
8
use bevy_ecs::{resource::Resource, system::Res};
9
use bevy_platform::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
10
use bevy_render::{Extract, ExtractSchedule, RenderApp};
11
12
use crate::{Material, MaterialBindGroupAllocators};
13
14
pub struct MaterialAllocatorDiagnosticPlugin<M: Material> {
15
suffix: &'static str,
16
_phantom: PhantomData<M>,
17
}
18
19
impl<M: Material> MaterialAllocatorDiagnosticPlugin<M> {
20
pub fn new(suffix: &'static str) -> Self {
21
Self {
22
suffix,
23
_phantom: PhantomData,
24
}
25
}
26
}
27
28
impl<M: Material> Default for MaterialAllocatorDiagnosticPlugin<M> {
29
fn default() -> Self {
30
Self {
31
suffix: " materials",
32
_phantom: PhantomData,
33
}
34
}
35
}
36
37
impl<M: Material> MaterialAllocatorDiagnosticPlugin<M> {
38
/// Get the [`DiagnosticPath`] for slab count
39
pub fn slabs_diagnostic_path() -> DiagnosticPath {
40
DiagnosticPath::from_components(["material_allocator_slabs", type_name::<M>()])
41
}
42
/// Get the [`DiagnosticPath`] for total slabs size
43
pub fn slabs_size_diagnostic_path() -> DiagnosticPath {
44
DiagnosticPath::from_components(["material_allocator_slabs_size", type_name::<M>()])
45
}
46
/// Get the [`DiagnosticPath`] for material allocations
47
pub fn allocations_diagnostic_path() -> DiagnosticPath {
48
DiagnosticPath::from_components(["material_allocator_allocations", type_name::<M>()])
49
}
50
}
51
52
impl<M: Material> Plugin for MaterialAllocatorDiagnosticPlugin<M> {
53
fn build(&self, app: &mut bevy_app::App) {
54
app.register_diagnostic(
55
Diagnostic::new(Self::slabs_diagnostic_path()).with_suffix(" slabs"),
56
)
57
.register_diagnostic(
58
Diagnostic::new(Self::slabs_size_diagnostic_path()).with_suffix(" bytes"),
59
)
60
.register_diagnostic(
61
Diagnostic::new(Self::allocations_diagnostic_path()).with_suffix(self.suffix),
62
)
63
.init_resource::<MaterialAllocatorMeasurements<M>>()
64
.add_systems(PreUpdate, add_material_allocator_measurement::<M>);
65
66
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
67
render_app.add_systems(ExtractSchedule, measure_allocator::<M>);
68
}
69
}
70
}
71
72
#[derive(Debug, Resource)]
73
struct MaterialAllocatorMeasurements<M: Material> {
74
slabs: AtomicUsize,
75
slabs_size: AtomicUsize,
76
allocations: AtomicU64,
77
_phantom: PhantomData<M>,
78
}
79
80
impl<M: Material> Default for MaterialAllocatorMeasurements<M> {
81
fn default() -> Self {
82
Self {
83
slabs: AtomicUsize::default(),
84
slabs_size: AtomicUsize::default(),
85
allocations: AtomicU64::default(),
86
_phantom: PhantomData,
87
}
88
}
89
}
90
91
fn add_material_allocator_measurement<M: Material>(
92
mut diagnostics: Diagnostics,
93
measurements: Res<MaterialAllocatorMeasurements<M>>,
94
) {
95
diagnostics.add_measurement(
96
&MaterialAllocatorDiagnosticPlugin::<M>::slabs_diagnostic_path(),
97
|| measurements.slabs.load(Ordering::Relaxed) as f64,
98
);
99
diagnostics.add_measurement(
100
&MaterialAllocatorDiagnosticPlugin::<M>::slabs_size_diagnostic_path(),
101
|| measurements.slabs_size.load(Ordering::Relaxed) as f64,
102
);
103
diagnostics.add_measurement(
104
&MaterialAllocatorDiagnosticPlugin::<M>::allocations_diagnostic_path(),
105
|| measurements.allocations.load(Ordering::Relaxed) as f64,
106
);
107
}
108
109
fn measure_allocator<M: Material + Any>(
110
measurements: Extract<Res<MaterialAllocatorMeasurements<M>>>,
111
allocators: Res<MaterialBindGroupAllocators>,
112
) {
113
if let Some(allocator) = allocators.get(&TypeId::of::<M>()) {
114
measurements
115
.slabs
116
.store(allocator.slab_count(), Ordering::Relaxed);
117
measurements
118
.slabs_size
119
.store(allocator.slabs_size(), Ordering::Relaxed);
120
measurements
121
.allocations
122
.store(allocator.allocations(), Ordering::Relaxed);
123
}
124
}
125
126