diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 770ad69533ec4..117876078ede0 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -99,7 +99,10 @@ use batching::gpu_preprocessing::BatchingPlugin; use bevy_app::{App, AppLabel, Plugin, SubApp}; use bevy_asset::{AssetApp, AssetServer}; use bevy_derive::Deref; -use bevy_ecs::{prelude::*, schedule::ScheduleLabel}; +use bevy_ecs::{ + prelude::*, + schedule::{InternedScheduleLabel, ScheduleLabel}, +}; use bevy_platform::time::Instant; use bevy_shader::{load_shader_library, Shader, ShaderLoader}; use bevy_time::TimeSender; @@ -233,11 +236,48 @@ impl GpuResourceAppExt for SubApp { } } -/// The render recovery schedule. This schedule runs the [`Render`] schedule if +/// The render recovery schedule. This schedule runs the [`RenderScheduleOrder`] schedules if /// we are in [`RenderState::Ready`], and is otherwise hidden from users. #[derive(ScheduleLabel, Debug, Hash, PartialEq, Eq, Clone)] struct RenderRecovery; +/// Defines the schedules to be run for the rendering, including their order. +#[derive(Resource, Debug)] +pub struct RenderScheduleOrder { + /// The labels to run for the rendering schedule (in the order they will be run). + pub labels: Vec, +} + +impl Default for RenderScheduleOrder { + fn default() -> Self { + Self { + labels: vec![Render.intern()], + } + } +} + +impl RenderScheduleOrder { + /// Adds the given `schedule` after the `after` schedule + pub fn insert_after(&mut self, after: impl ScheduleLabel, schedule: impl ScheduleLabel) { + let index = self + .labels + .iter() + .position(|current| (**current).eq(&after)) + .unwrap_or_else(|| panic!("Expected {after:?} to exist")); + self.labels.insert(index + 1, schedule.intern()); + } + + /// Adds the given `schedule` before the `before` schedule + pub fn insert_before(&mut self, before: impl ScheduleLabel, schedule: impl ScheduleLabel) { + let index = self + .labels + .iter() + .position(|current| (**current).eq(&before)) + .unwrap_or_else(|| panic!("Expected {before:?} to exist")); + self.labels.insert(index, schedule.intern()); + } +} + /// The main render schedule. #[derive(ScheduleLabel, Debug, Hash, PartialEq, Eq, Clone, Default)] pub struct Render; @@ -341,6 +381,7 @@ impl Plugin for RenderPlugin { app.init_resource::() .init_resource::(); if let Some(render_app) = app.get_sub_app_mut(RenderApp) { + render_app.init_resource::(); render_app.init_resource::(); render_app.init_gpu_resource::(); render_app.insert_resource(sender); @@ -415,7 +456,11 @@ fn renderer_is_ready(state: Res) -> bool { } fn run_render_schedule(world: &mut World) { - world.run_schedule(Render); + world.resource_scope(|world, order: Mut| { + for &label in &order.labels { + let _ = world.try_run_schedule(label); + } + }); } fn send_time(time_sender: Res) {