diff --git a/bevy_app/src/app_builder.rs b/bevy_app/src/app_builder.rs index 586499efae..a294dc0313 100644 --- a/bevy_app/src/app_builder.rs +++ b/bevy_app/src/app_builder.rs @@ -151,6 +151,7 @@ impl AppBuilder { .add_stage(stage::FIRST) .add_stage(stage::EVENT_UPDATE) .add_stage(stage::UPDATE) + .add_stage(stage::POST_UPDATE) .add_stage(stage::LAST) } @@ -162,6 +163,14 @@ impl AppBuilder { self.add_system(system) } + pub fn build_system_on_stage(&mut self, stage_name: &str, build: F) -> &mut Self + where + F: Fn(&mut Resources) -> Box, + { + let system = build(self.resources_mut()); + self.add_system_to_stage(stage_name, system) + } + pub fn add_system_to_stage( &mut self, stage_name: &str, diff --git a/bevy_render/src/camera.rs b/bevy_render/src/camera.rs index 942549a401..ffb0ec4620 100644 --- a/bevy_render/src/camera.rs +++ b/bevy_render/src/camera.rs @@ -1,4 +1,7 @@ +use bevy_app::{Events, GetEventReader}; +use bevy_window::WindowResized; use glam::Mat4; +use legion::prelude::*; #[derive(Default)] pub struct ActiveCamera; @@ -115,4 +118,27 @@ impl Camera { } } } -} \ No newline at end of file +} + +pub fn camera_update_system(resources: &mut Resources) -> Box { + let mut window_resized_event_reader = resources.get_event_reader::(); + SystemBuilder::new("camera_update") + .read_resource::>() + .with_query(>::query()) + .build(move |_, world, window_resized_events, query| { + // TODO: refactor this to "window_resized_events.latest()" + let primary_window_resized_event = window_resized_events + .iter(&mut window_resized_event_reader) + .rev() + .filter(|event| event.is_primary) + .next(); + if let Some(primary_window_resized_event) = primary_window_resized_event { + for mut camera in query.iter_mut(world) { + camera.update( + primary_window_resized_event.width, + primary_window_resized_event.height, + ); + } + } + }) +} diff --git a/bevy_render/src/lib.rs b/bevy_render/src/lib.rs index 460a04c1e6..62824e38e6 100644 --- a/bevy_render/src/lib.rs +++ b/bevy_render/src/lib.rs @@ -83,8 +83,6 @@ impl RenderPlugin { resources.get_event_reader::(), )) .add_resource_provider(LightResourceProvider::new(10)) - // TODO: move me to ui crate - // .add_resource_provider(UiResourceProvider::new()) .add_resource_provider(MeshResourceProvider::new()) .add_resource_provider(UniformResourceProvider::::new(true)) .add_resource_provider(UniformResourceProvider::::new(true)) @@ -98,7 +96,9 @@ impl AppPlugin for RenderPlugin { let mut asset_batchers = AssetBatchers::default(); asset_batchers.batch_types2::(); app.add_system(build_entity_render_resource_assignments_system()) - .add_stage_after(stage::UPDATE, RENDER_STAGE) + .build_system_on_stage(stage::POST_UPDATE, camera::camera_update_system) + .add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system()) + .add_stage_after(stage::POST_UPDATE, RENDER_STAGE) .add_resource(RenderGraph::default()) .add_resource(AssetStorage::::new()) .add_resource(AssetStorage::::new()) diff --git a/bevy_render/src/mesh.rs b/bevy_render/src/mesh.rs index d34091cfca..fd2c6fe2e8 100644 --- a/bevy_render/src/mesh.rs +++ b/bevy_render/src/mesh.rs @@ -1,6 +1,7 @@ -use crate::Vertex; -use bevy_asset::Asset; +use crate::{render_resource::AssetBatchers, Vertex, Renderable}; +use bevy_asset::{Handle, Asset}; use glam::*; +use legion::prelude::*; pub enum MeshType { Cube, @@ -118,3 +119,15 @@ pub fn create_cube() -> (Vec, Vec) { pub fn create_plane(size: f32) -> (Vec, Vec) { create_quad(vec2(size, size)) } + + +pub fn mesh_batcher_system() -> Box { + SystemBuilder::new("mesh_batcher") + .write_resource::() + .with_query(<(Read>, Read)>::query().filter(changed::>())) + .build(|_, world, asset_batchers, query| { + for (entity, (mesh_handle, _renderable)) in query.iter_entities(world) { + asset_batchers.set_entity_handle(entity, *mesh_handle); + } + }) +} \ No newline at end of file diff --git a/bevy_render/src/render_resource/resource_provider.rs b/bevy_render/src/render_resource/resource_provider.rs index 5a44a52866..24824ca17b 100644 --- a/bevy_render/src/render_resource/resource_provider.rs +++ b/bevy_render/src/render_resource/resource_provider.rs @@ -9,8 +9,12 @@ pub trait ResourceProvider { _resources: &Resources, ) { } + + // TODO: make this read-only fn update(&mut self, _render_context: &mut dyn RenderContext, _world: &mut World, _resources: &Resources) { } + + // TODO: remove this fn finish_update( &mut self, _render_context: &mut dyn RenderContext, @@ -18,4 +22,10 @@ pub trait ResourceProvider { _resources: &Resources, ) { } + + /// Runs after resources have been created on the gpu. In general systems here write gpu-related resources back to entities in this step + fn post_update(&mut self, _render_context: &dyn RenderContext, _world: &mut World, _resources: &Resources) { + + } + } diff --git a/bevy_render/src/render_resource/resource_providers/camera2d_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/camera2d_resource_provider.rs index 282d07b64c..a8ccba20af 100644 --- a/bevy_render/src/render_resource/resource_providers/camera2d_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/camera2d_resource_provider.rs @@ -27,31 +27,11 @@ impl Camera2dResourceProvider { window_resized_event_reader, } } -} -impl ResourceProvider for Camera2dResourceProvider { - fn initialize( + fn update_read_only( &mut self, render_context: &mut dyn RenderContext, - _world: &mut World, - resources: &Resources, - ) { - let buffer = render_context.create_buffer(BufferInfo { - size: std::mem::size_of::<[[f32; 4]; 4]>(), - buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, - ..Default::default() - }); - - let mut render_resource_assignments = - resources.get_mut::().unwrap(); - render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer); - self.camera_buffer = Some(buffer); - } - - fn update( - &mut self, - render_context: &mut dyn RenderContext, - world: &mut World, + world: &World, resources: &Resources, ) { let window_resized_events = resources.get::>().unwrap(); @@ -61,14 +41,10 @@ impl ResourceProvider for Camera2dResourceProvider { .filter(|event| event.is_primary) .next(); - if let Some(primary_window_resized_event) = primary_window_resized_event { + if let Some(_) = primary_window_resized_event { let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); - for (mut camera, _) in <(Write, Read)>::query().iter_mut(world) + for (camera, _) in <(Read, Read)>::query().iter(world) { - camera.update( - primary_window_resized_event.width, - primary_window_resized_event.height, - ); let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d(); if let Some(old_tmp_buffer) = self.tmp_buffer { @@ -97,3 +73,32 @@ impl ResourceProvider for Camera2dResourceProvider { } } } + +impl ResourceProvider for Camera2dResourceProvider { + fn initialize( + &mut self, + render_context: &mut dyn RenderContext, + _world: &mut World, + resources: &Resources, + ) { + let buffer = render_context.create_buffer(BufferInfo { + size: std::mem::size_of::<[[f32; 4]; 4]>(), + buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, + ..Default::default() + }); + + let mut render_resource_assignments = + resources.get_mut::().unwrap(); + render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer); + self.camera_buffer = Some(buffer); + } + + fn update( + &mut self, + render_context: &mut dyn RenderContext, + world: &mut World, + resources: &Resources, + ) { + self.update_read_only(render_context, world, resources); + } +} diff --git a/bevy_render/src/render_resource/resource_providers/camera_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/camera_resource_provider.rs index 9e9abfec35..16a2b19aef 100644 --- a/bevy_render/src/render_resource/resource_providers/camera_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/camera_resource_provider.rs @@ -5,7 +5,8 @@ use crate::{ resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, ResourceProvider, }, - ActiveCamera, Camera, renderer_2::RenderContext, + renderer_2::RenderContext, + ActiveCamera, Camera, }; use bevy_app::{EventReader, Events}; @@ -27,43 +28,19 @@ impl CameraResourceProvider { window_resized_event_reader, } } -} -impl ResourceProvider for CameraResourceProvider { - fn initialize( - &mut self, - render_context: &mut dyn RenderContext, - _world: &mut World, - resources: &Resources, - ) { - let buffer = render_context.create_buffer(BufferInfo { - size: std::mem::size_of::<[[f32; 4]; 4]>(), - buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, - ..Default::default() - }); - - let mut render_resource_assignments = - resources.get_mut::().unwrap(); - render_resource_assignments.set(resource_name::uniform::CAMERA, buffer); - self.camera_buffer = Some(buffer); - } - - fn update(&mut self, render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources) { + pub fn update_read_only(&mut self, world: &World, resources: &Resources, render_context: &mut dyn RenderContext) { let window_resized_events = resources.get::>().unwrap(); let primary_window_resized_event = window_resized_events .iter(&mut self.window_resized_event_reader) .rev() .filter(|event| event.is_primary) .next(); - if let Some(primary_window_resized_event) = primary_window_resized_event { + if let Some(_) = primary_window_resized_event { let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); - for (mut camera, local_to_world, _) in - <(Write, Read, Read)>::query().iter_mut(world) + for (camera, local_to_world, _) in + <(Read, Read, Read)>::query().iter(world) { - camera.update( - primary_window_resized_event.width, - primary_window_resized_event.height, - ); let camera_matrix: [[f32; 4]; 4] = (camera.view_matrix * local_to_world.0).to_cols_array_2d(); @@ -93,3 +70,32 @@ impl ResourceProvider for CameraResourceProvider { } } } + +impl ResourceProvider for CameraResourceProvider { + fn initialize( + &mut self, + render_context: &mut dyn RenderContext, + _world: &mut World, + resources: &Resources, + ) { + let buffer = render_context.create_buffer(BufferInfo { + size: std::mem::size_of::<[[f32; 4]; 4]>(), + buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, + ..Default::default() + }); + + let mut render_resource_assignments = + resources.get_mut::().unwrap(); + render_resource_assignments.set(resource_name::uniform::CAMERA, buffer); + self.camera_buffer = Some(buffer); + } + + fn update( + &mut self, + render_context: &mut dyn RenderContext, + world: &mut World, + resources: &Resources, + ) { + self.update_read_only(world, resources, render_context); + } +} diff --git a/bevy_render/src/render_resource/resource_providers/light_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/light_resource_provider.rs index 2d5304db1a..3a2cfdb1e1 100644 --- a/bevy_render/src/render_resource/resource_providers/light_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/light_resource_provider.rs @@ -33,30 +33,7 @@ impl LightResourceProvider { tmp_count_buffer: None, } } -} - -impl ResourceProvider for LightResourceProvider { - fn initialize( - &mut self, - render_context: &mut dyn RenderContext, - _world: &mut World, - resources: &Resources, - ) { - let light_uniform_size = - std::mem::size_of::() + self.max_lights * std::mem::size_of::(); - - let buffer = render_context.create_buffer(BufferInfo { - size: light_uniform_size, - buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST, - ..Default::default() - }); - let mut render_resource_assignments = - resources.get_mut::().unwrap(); - render_resource_assignments.set(resource_name::uniform::LIGHTS, buffer); - self.light_buffer = Some(buffer); - } - - fn update(&mut self, render_context: &mut dyn RenderContext, world: &mut World, _resources: &Resources) { + fn update_read_only(&mut self, render_context: &mut dyn RenderContext, world: &World) { if self.lights_are_dirty { let light_query = <(Read, Read, Read)>::query(); let light_count = light_query.iter(world).count(); @@ -123,3 +100,29 @@ impl ResourceProvider for LightResourceProvider { } } } + +impl ResourceProvider for LightResourceProvider { + fn initialize( + &mut self, + render_context: &mut dyn RenderContext, + _world: &mut World, + resources: &Resources, + ) { + let light_uniform_size = + std::mem::size_of::() + self.max_lights * std::mem::size_of::(); + + let buffer = render_context.create_buffer(BufferInfo { + size: light_uniform_size, + buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST, + ..Default::default() + }); + let mut render_resource_assignments = + resources.get_mut::().unwrap(); + render_resource_assignments.set(resource_name::uniform::LIGHTS, buffer); + self.light_buffer = Some(buffer); + } + + fn update(&mut self, render_context: &mut dyn RenderContext, world: &mut World, _resources: &Resources) { + self.update_read_only(render_context, world); + } +} diff --git a/bevy_render/src/render_resource/resource_providers/mesh_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/mesh_resource_provider.rs index 5ba6525f17..8c98496a53 100644 --- a/bevy_render/src/render_resource/resource_providers/mesh_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/mesh_resource_provider.rs @@ -40,7 +40,7 @@ impl MeshResourceProvider { fn setup_mesh_resources( render_context: &mut dyn RenderContext, - mesh_storage: &mut AssetStorage, + mesh_storage: &AssetStorage, handle: Handle, render_resource_assignments: &mut RenderResourceAssignments, ) { @@ -91,10 +91,6 @@ impl ResourceProvider for MeshResourceProvider { } fn update(&mut self, _render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources) { - let mut asset_batchers = resources.get_mut::().unwrap(); - for (entity, (mesh_handle, _renderable)) in self.mesh_query.iter_entities_mut(world) { - asset_batchers.set_entity_handle(entity, *mesh_handle); - } } fn finish_update( @@ -103,7 +99,7 @@ impl ResourceProvider for MeshResourceProvider { _world: &mut World, resources: &Resources, ) { - let mut mesh_storage = resources.get_mut::>().unwrap(); + let mut mesh_storage = resources.get::>().unwrap(); let mut asset_batchers = resources.get_mut::().unwrap(); // this scope is necessary because the Fetch pointer behaves weirdly @@ -114,7 +110,7 @@ impl ResourceProvider for MeshResourceProvider { log::trace!("setup mesh for {:?}", batch.render_resource_assignments.id); Self::setup_mesh_resources( render_context, - &mut mesh_storage, + &mesh_storage, handle, &mut batch.render_resource_assignments, );