Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/stress_tests/many_meshlet_materials.rs
30632 views
1
//! A stress test for the Meshlet pipeline specialization overhead.
2
//!
3
//! Run with `--unique-materials` to trigger the unconditional specialization bug.
4
//! Run without it (shared material) to see the baseline performance.
5
6
use argh::FromArgs;
7
use bevy::{
8
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
9
pbr::experimental::meshlet::{MeshletMesh3d, MeshletPlugin},
10
prelude::*,
11
window::{PresentMode, WindowResolution},
12
winit::WinitSettings,
13
};
14
15
#[derive(FromArgs, Resource)]
16
#[argh(description = "Meshlet Material Stress Test")]
17
struct Args {
18
/// the grid size (e.g., 50 means 50x50 = 2500 meshlets)
19
#[argh(option, short = 'n', default = "50")]
20
grid_size: usize,
21
22
/// if set, every meshlet gets a unique material asset.
23
/// This triggers the unconditional pipeline specialization bug in `prepare_material_meshlet_meshes`.
24
#[argh(switch)]
25
unique_materials: bool,
26
}
27
28
const ASSET_URL: &str =
29
"https://github.com/bevyengine/bevy_asset_files/raw/6dccaef517bde74d1969734703709aead7211dbc/meshlet/bunny.meshlet_mesh";
30
31
fn main() {
32
let args: Args = argh::from_env();
33
34
warn!(include_str!("warning_string.txt"));
35
println!("Meshlet Stress Test");
36
println!(
37
"Grid size: {}x{} ({} instances)",
38
args.grid_size,
39
args.grid_size,
40
args.grid_size * args.grid_size
41
);
42
println!(
43
"Materials: {}",
44
if args.unique_materials {
45
"UNIQUE"
46
} else {
47
"SHARED"
48
}
49
);
50
51
App::new()
52
.add_plugins((
53
DefaultPlugins.set(WindowPlugin {
54
primary_window: Some(Window {
55
present_mode: PresentMode::AutoNoVsync,
56
resolution: WindowResolution::new(1920, 1080).with_scale_factor_override(1.0),
57
..default()
58
}),
59
..default()
60
}),
61
FrameTimeDiagnosticsPlugin::default(),
62
LogDiagnosticsPlugin::default(),
63
MeshletPlugin {
64
cluster_buffer_slots: 8192,
65
},
66
))
67
.insert_resource(WinitSettings::continuous())
68
.insert_resource(args)
69
.add_systems(Startup, setup)
70
.run();
71
}
72
73
fn setup(
74
mut commands: Commands,
75
args: Res<Args>,
76
asset_server: Res<AssetServer>,
77
mut materials: ResMut<Assets<StandardMaterial>>,
78
) {
79
let meshlet_handle = asset_server.load(ASSET_URL);
80
81
let n = args.grid_size;
82
let spacing = 2.0;
83
84
commands.spawn((
85
Camera3d::default(),
86
Transform::from_xyz(0.0, n as f32, n as f32 * 1.5).looking_at(Vec3::ZERO, Vec3::Y),
87
Msaa::Off,
88
));
89
90
commands.spawn((
91
DirectionalLight {
92
illuminance: 3000.0,
93
shadow_maps_enabled: true,
94
..default()
95
},
96
Transform::from_rotation(Quat::from_euler(
97
EulerRot::ZYX,
98
0.0,
99
1.0,
100
-std::f32::consts::FRAC_PI_4,
101
)),
102
));
103
104
let shared_material = materials.add(StandardMaterial {
105
base_color: Color::WHITE,
106
..default()
107
});
108
109
for x in 0..n {
110
for z in 0..n {
111
let material = if args.unique_materials {
112
materials.add(StandardMaterial {
113
base_color: Color::srgb(x as f32 / n as f32, 0.5, z as f32 / n as f32),
114
..default()
115
})
116
} else {
117
shared_material.clone()
118
};
119
120
commands.spawn((
121
MeshletMesh3d(meshlet_handle.clone()),
122
MeshMaterial3d(material),
123
Transform::from_xyz(
124
x as f32 * spacing - n as f32,
125
0.0,
126
z as f32 * spacing - n as f32,
127
),
128
));
129
}
130
}
131
}
132
133