Skip to content

Commit 81d02c5

Browse files
committed
Add test to check leaks through churn
1 parent c520d47 commit 81d02c5

File tree

1 file changed

+81
-10
lines changed

1 file changed

+81
-10
lines changed

tests/render_asset_leaks.rs

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ use bevy::{
99
audio::AudioPlugin,
1010
color::Color,
1111
diagnostic::{DiagnosticsStore, LogDiagnosticsPlugin},
12-
ecs::system::{Commands, Local, Res, ResMut},
12+
ecs::system::{Res, ResMut},
1313
math::primitives::Sphere,
1414
pbr::{
15-
diagnostic::MaterialAllocatorDiagnosticPlugin, Material, MeshMaterial3d, PreparedMaterial,
16-
StandardMaterial,
15+
diagnostic::MaterialAllocatorDiagnosticPlugin, Material, PreparedMaterial, StandardMaterial,
1716
},
1817
render::{
1918
diagnostic::{MeshAllocatorDiagnosticPlugin, RenderAssetDiagnosticPlugin},
20-
mesh::{Mesh, Mesh3d, Meshable, RenderMesh},
19+
mesh::{Mesh, Meshable, RenderMesh},
2120
},
2221
window::WindowPlugin,
2322
winit::WinitPlugin,
2423
DefaultPlugins,
2524
};
25+
use bevy_ecs::{resource::Resource, system::Commands};
2626

2727
#[test]
2828
fn check_mesh_leak() {
@@ -54,6 +54,7 @@ fn check_mesh_leak() {
5454
}
5555
}
5656

57+
#[ignore = "FIXME Failing test"]
5758
#[test]
5859
fn check_standard_material_leak() {
5960
let mut app = App::new();
@@ -87,31 +88,101 @@ fn check_standard_material_leak() {
8788
}
8889
}
8990

91+
#[test]
92+
fn check_mesh_churn_leak() {
93+
let mut app = App::new();
94+
app.add_plugins((
95+
DefaultPlugins
96+
.build()
97+
.disable::<AudioPlugin>()
98+
.disable::<WinitPlugin>()
99+
.disable::<WindowPlugin>(),
100+
LogDiagnosticsPlugin {
101+
wait_duration: Duration::ZERO,
102+
..Default::default()
103+
},
104+
RenderAssetDiagnosticPlugin::<RenderMesh>::new(" meshes"),
105+
MeshAllocatorDiagnosticPlugin,
106+
))
107+
.add_systems(Startup, mesh_setup)
108+
.add_systems(Update, (churn::<Mesh>, crash_on_mesh_leak_detection));
109+
110+
app.finish();
111+
app.cleanup();
112+
113+
for _ in 0..100 {
114+
app.update();
115+
}
116+
}
117+
118+
#[ignore = "FIXME Failing test"]
119+
#[test]
120+
fn check_standard_material_churn_leak() {
121+
let mut app = App::new();
122+
app.add_plugins((
123+
DefaultPlugins
124+
.build()
125+
.disable::<AudioPlugin>()
126+
.disable::<WinitPlugin>()
127+
.disable::<WindowPlugin>(),
128+
LogDiagnosticsPlugin {
129+
wait_duration: Duration::ZERO,
130+
..Default::default()
131+
},
132+
RenderAssetDiagnosticPlugin::<PreparedMaterial<StandardMaterial>>::new(" materials"),
133+
MaterialAllocatorDiagnosticPlugin::<StandardMaterial>::default(),
134+
))
135+
.add_systems(Startup, mesh_setup)
136+
.add_systems(
137+
Update,
138+
(
139+
churn::<StandardMaterial>,
140+
crash_on_material_leak_detection::<StandardMaterial>,
141+
),
142+
);
143+
144+
app.finish();
145+
app.cleanup();
146+
147+
for _ in 0..100 {
148+
app.update();
149+
}
150+
}
151+
152+
#[derive(Resource)]
153+
struct Leaker<A: Asset>(Vec<Handle<A>>);
154+
90155
fn mesh_setup(
91156
mut commands: Commands,
92157
mut meshes: ResMut<Assets<Mesh>>,
93158
mut materials: ResMut<Assets<StandardMaterial>>,
94-
mut mesh_leaker: Local<Vec<Handle<Mesh>>>,
95-
mut material_leaker: Local<Vec<Handle<StandardMaterial>>>,
96159
) {
97160
bevy::log::info!("Mesh setup");
98-
commands.spawn((
99-
Mesh3d(meshes.add(Sphere::new(1.).mesh().ico(79).unwrap())),
100-
MeshMaterial3d(materials.add(Color::WHITE)),
101-
));
102161

162+
let mut mesh_leaker = Vec::with_capacity(16);
103163
for _ in 0..16 {
104164
mesh_leaker.push(meshes.add(Sphere::new(1.).mesh().ico(79).unwrap()));
105165
}
166+
commands.insert_resource(Leaker(mesh_leaker));
167+
let mut material_leaker = Vec::with_capacity(1000);
106168
for _ in 0..1000 {
107169
material_leaker.push(materials.add(Color::WHITE));
108170
}
171+
commands.insert_resource(Leaker(material_leaker));
109172
}
110173

111174
fn touch_mutably<A: Asset>(mut assets: ResMut<Assets<A>>) {
112175
for _ in assets.iter_mut() {}
113176
}
114177

178+
fn churn<A: Asset>(mut assets: ResMut<Assets<A>>, mut leaker: ResMut<Leaker<A>>) {
179+
let all_ids = leaker.0.drain(..).collect::<Vec<_>>();
180+
for id in all_ids {
181+
let asset = assets.remove(id.id()).unwrap();
182+
leaker.0.push(assets.add(asset));
183+
}
184+
}
185+
115186
fn crash_on_mesh_leak_detection(diagnostic_store: Res<DiagnosticsStore>) {
116187
if let (Some(render_meshes), Some(allocations)) = (
117188
diagnostic_store

0 commit comments

Comments
 (0)