-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
With the latest performance fixes on master, there is an issue with creating meshes in stages that happen after mesh_resource_provider_system. I've debugged it and reduced it to this sample case (from my actual code which hits this).
This code will panic on bevy master:
With: thread 'main' panicked at 'Attribute Vertex_Position is required by shader, but not supplied by mesh. Either remove the attribute from the shader or supply the attribute (Vertex_Position) to the mesh. ', crates\bevy_render\src\pipeline\pipeline_compiler.rs:223:17
use bevy::prelude::*;
fn main() {
App::build()
.add_plugins(DefaultPlugins)
// add_stage ends up adding it last in the stage order?
.add_stage("panic_due_to_stage_order")
.add_system_to_stage("panic_due_to_stage_order", panic_due_to_stage_order)
.run();
}
fn panic_due_to_stage_order(commands: &mut Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
commands.spawn(SpriteBundle {
material: materials.add(ColorMaterial::color(Color::RED)),
..Default::default()
});
}
The issue is that in the new optimized mesh_resource_provider_system implementation we are using Changed<> to detect when we need to initialize the render_pipeline for the mesh. Unfortunately, the mesh has not yet been flagged for Changed at the time the mesh_resource_provider_system runs and Changed gets reset every frame.
Ideally it shouldn't matter at what stage you spawn your entity/components.
Some half-baked ideas on how to fix this in bevy (obviously without reverting the perf improvement):
- Just run mesh_resource_provider_system again at the end of the frame, it could capture the entities that Changed and weren't processed in the first pass. This seems a bit hacky. Also there's no way currently to pin a system at the end anyway.
- Introduce a ChangedLastFrame<> query filter. This would allow us to build a system that can handle changes to entities and the order of the system doesn't matter. In this mesh system case we would check both this ChangedLastFrame and Changed<>
I'd like to contribute a fix to resolve this, if we can figure out what's a good way to fix this... Perhaps there's a trivial way I am not seeing!