From 0472cbfc7ca9ae71213b1f33d1433ca6d73886ff Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Thu, 28 May 2020 17:32:51 -0700 Subject: [PATCH] start porting "query" systems from SystemBuilder to functions --- crates/bevy_legion/legion_core/src/lib.rs | 2 +- .../legion_fn_system_macro/src/lib.rs | 2 +- crates/bevy_legion/legion_systems/src/lib.rs | 2 + crates/bevy_pbr/src/nodes/lights_node.rs | 177 +++++++++--------- crates/bevy_render/src/camera.rs | 32 ++-- crates/bevy_render/src/mesh.rs | 166 ++++++++-------- crates/bevy_wgpu/src/renderer/systems.rs | 39 ++++ 7 files changed, 226 insertions(+), 194 deletions(-) diff --git a/crates/bevy_legion/legion_core/src/lib.rs b/crates/bevy_legion/legion_core/src/lib.rs index 70b98aa939..8c0ab33911 100644 --- a/crates/bevy_legion/legion_core/src/lib.rs +++ b/crates/bevy_legion/legion_core/src/lib.rs @@ -28,7 +28,7 @@ pub mod prelude { entity::Entity, event::Event, filter::filter_fns::*, - query::{IntoQuery, Query, Read, Tagged, TryRead, TryWrite, Write}, + query::{IntoQuery, Query as FilteredQuery, Read, Tagged, TryRead, TryWrite, Write}, world::{Universe, World}, }; } diff --git a/crates/bevy_legion/legion_fn_system_macro/src/lib.rs b/crates/bevy_legion/legion_fn_system_macro/src/lib.rs index 8878c43a6b..3574177e08 100644 --- a/crates/bevy_legion/legion_fn_system_macro/src/lib.rs +++ b/crates/bevy_legion/legion_fn_system_macro/src/lib.rs @@ -270,7 +270,7 @@ pub fn impl_fn_query_systems(_input: TokenStream) -> TokenStream { fn system_id(mut self, id: SystemId) -> Box { let resource_access: Access = #resource_access; let component_access: Access = #component_access; - + let run_fn = FuncSystemFnWrapper( move |_command_buffer, _world, diff --git a/crates/bevy_legion/legion_systems/src/lib.rs b/crates/bevy_legion/legion_systems/src/lib.rs index 15967be67a..5b1c3faee1 100644 --- a/crates/bevy_legion/legion_systems/src/lib.rs +++ b/crates/bevy_legion/legion_systems/src/lib.rs @@ -21,5 +21,7 @@ pub mod prelude { ResMut, System, SystemBuilder, + Query, + SubWorld }; } diff --git a/crates/bevy_pbr/src/nodes/lights_node.rs b/crates/bevy_pbr/src/nodes/lights_node.rs index f2ee81d140..504496b657 100644 --- a/crates/bevy_pbr/src/nodes/lights_node.rs +++ b/crates/bevy_pbr/src/nodes/lights_node.rs @@ -54,106 +54,99 @@ impl SystemNode for LightsNode { let mut tmp_light_buffer = None; let mut command_queue = self.command_queue.clone(); let max_lights = self.max_lights; - SystemBuilder::new("light_node") - .read_resource::() - // TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same - .write_resource::() - .with_query(<(Read, Read, Read)>::query()) - .build( - move |_, - world, - (render_resource_context, ref mut render_resource_assignments), - query| { - if !lights_are_dirty { - return; - } + (move |world: &mut SubWorld, + render_resources: Res, + // TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same + mut render_resource_assignments: ResMut, + query: &mut Query<(Read, Read, Read)>| { + if !lights_are_dirty { + return; + } - let render_resources = &render_resource_context.context; - if light_buffer.is_none() { - let light_uniform_size = std::mem::size_of::() - + max_lights * std::mem::size_of::(); + let render_resources = &render_resources.context; + if light_buffer.is_none() { + let light_uniform_size = std::mem::size_of::() + + max_lights * std::mem::size_of::(); - let buffer = render_resources.create_buffer(BufferInfo { - size: light_uniform_size, - buffer_usage: BufferUsage::UNIFORM - | BufferUsage::COPY_SRC - | BufferUsage::COPY_DST, - ..Default::default() - }); - render_resource_assignments.set( - resource_name::uniform::LIGHTS, - RenderResourceAssignment::Buffer { - resource: buffer, - range: 0..light_uniform_size as u64, - dynamic_index: None, - }, - ); - light_buffer = Some(buffer); - } + let buffer = render_resources.create_buffer(BufferInfo { + size: light_uniform_size, + buffer_usage: BufferUsage::UNIFORM + | BufferUsage::COPY_SRC + | BufferUsage::COPY_DST, + ..Default::default() + }); + render_resource_assignments.set( + resource_name::uniform::LIGHTS, + RenderResourceAssignment::Buffer { + resource: buffer, + range: 0..light_uniform_size as u64, + dynamic_index: None, + }, + ); + light_buffer = Some(buffer); + } - let light_count = query.iter(world).count(); + let light_count = query.iter(world).count(); - if light_count == 0 { - return; - } + if light_count == 0 { + return; + } - lights_are_dirty = false; - let size = std::mem::size_of::(); - let total_size = size * light_count; - let light_count_size = std::mem::size_of::(); + lights_are_dirty = false; + let size = std::mem::size_of::(); + let total_size = size * light_count; + let light_count_size = std::mem::size_of::(); - if let Some(old_tmp_light_buffer) = tmp_light_buffer { - render_resources.remove_buffer(old_tmp_light_buffer); - } + if let Some(old_tmp_light_buffer) = tmp_light_buffer { + render_resources.remove_buffer(old_tmp_light_buffer); + } - if let Some(old_tmp_count_buffer) = tmp_count_buffer { - render_resources.remove_buffer(old_tmp_count_buffer); - } + if let Some(old_tmp_count_buffer) = tmp_count_buffer { + render_resources.remove_buffer(old_tmp_count_buffer); + } - tmp_light_buffer = Some(render_resources.create_buffer_mapped( - BufferInfo { - size: total_size, - buffer_usage: BufferUsage::COPY_SRC, - ..Default::default() - }, - &mut |data, _renderer| { - for ((light, local_to_world, translation), slot) in - query.iter(world).zip(data.chunks_exact_mut(size)) - { - slot.copy_from_slice( - LightRaw::from(&light, &local_to_world.0, &translation) - .as_bytes(), - ); - } - }, - )); - tmp_count_buffer = Some(render_resources.create_buffer_mapped( - BufferInfo { - size: light_count_size, - buffer_usage: BufferUsage::COPY_SRC, - ..Default::default() - }, - &mut |data, _renderer| { - data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes()); - }, - )); - - command_queue.copy_buffer_to_buffer( - tmp_count_buffer.unwrap(), - 0, - light_buffer.unwrap(), - 0, - light_count_size as u64, - ); - - command_queue.copy_buffer_to_buffer( - tmp_light_buffer.unwrap(), - 0, - light_buffer.unwrap(), - light_count_size as u64, - total_size as u64, - ); + tmp_light_buffer = Some(render_resources.create_buffer_mapped( + BufferInfo { + size: total_size, + buffer_usage: BufferUsage::COPY_SRC, + ..Default::default() }, - ) + &mut |data, _renderer| { + for ((light, local_to_world, translation), slot) in + query.iter(world).zip(data.chunks_exact_mut(size)) + { + slot.copy_from_slice( + LightRaw::from(&light, &local_to_world.0, &translation).as_bytes(), + ); + } + }, + )); + tmp_count_buffer = Some(render_resources.create_buffer_mapped( + BufferInfo { + size: light_count_size, + buffer_usage: BufferUsage::COPY_SRC, + ..Default::default() + }, + &mut |data, _renderer| { + data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes()); + }, + )); + + command_queue.copy_buffer_to_buffer( + tmp_count_buffer.unwrap(), + 0, + light_buffer.unwrap(), + 0, + light_count_size as u64, + ); + + command_queue.copy_buffer_to_buffer( + tmp_light_buffer.unwrap(), + 0, + light_buffer.unwrap(), + light_count_size as u64, + total_size as u64, + ); + }).system() } } diff --git a/crates/bevy_render/src/camera.rs b/crates/bevy_render/src/camera.rs index 75426fcf51..e6a6f891ac 100644 --- a/crates/bevy_render/src/camera.rs +++ b/crates/bevy_render/src/camera.rs @@ -1,9 +1,9 @@ use bevy_app::{Events, GetEventReader}; -use bevy_window::WindowResized; use bevy_property::{Properties, Property}; +use bevy_window::WindowResized; use glam::Mat4; use legion::prelude::*; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Default, Properties)] pub struct ActiveCamera; @@ -127,19 +127,19 @@ impl Camera { 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| { - let primary_window_resized_event = window_resized_event_reader - .find_latest(&window_resized_events, |event| event.is_primary); - 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, - ); - } + (move |world: &mut SubWorld, + window_resized_events: Res>, + query: &mut Query>| { + let primary_window_resized_event = window_resized_event_reader + .find_latest(&window_resized_events, |event| event.is_primary); + 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, + ); } - }) + } + }) + .system() } diff --git a/crates/bevy_render/src/mesh.rs b/crates/bevy_render/src/mesh.rs index 8f89481636..848e855a1f 100644 --- a/crates/bevy_render/src/mesh.rs +++ b/crates/bevy_render/src/mesh.rs @@ -341,93 +341,91 @@ pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box() - .read_resource::>() - .read_resource::>>() - .with_query(<(Read>, Write)>::query()) - .build( - move |_, world, (render_resources, meshes, mesh_events), query| { - let render_resources = &*render_resources.context; - let mut changed_meshes = HashSet::new(); - for event in mesh_event_reader.iter(&mesh_events) { - match event { - AssetEvent::Created { handle } => { - changed_meshes.insert(*handle); - } - AssetEvent::Modified { handle } => { - changed_meshes.insert(*handle); - remove_current_mesh_resources(render_resources, *handle); - } - AssetEvent::Removed { handle } => { - remove_current_mesh_resources(render_resources, *handle); - // if mesh was modified and removed in the same update, ignore the modification - // events are ordered so future modification events are ok - changed_meshes.remove(handle); - } - } + (move |world: &mut SubWorld, + render_resources: Res, + meshes: Res>, + mesh_events: Res>>, + query: &mut Query<(Read>, Write)>| { + let render_resources = &*render_resources.context; + let mut changed_meshes = HashSet::new(); + for event in mesh_event_reader.iter(&mesh_events) { + match event { + AssetEvent::Created { handle } => { + changed_meshes.insert(*handle); } - - for changed_mesh_handle in changed_meshes.iter() { - if let Some(mesh) = meshes.get(changed_mesh_handle) { - let vertex_bytes = mesh - .get_vertex_buffer_bytes(&vertex_buffer_descriptor) - .unwrap(); - // TODO: use a staging buffer here - let vertex_buffer = render_resources.create_buffer_with_data( - BufferInfo { - buffer_usage: BufferUsage::VERTEX, - ..Default::default() - }, - &vertex_bytes, - ); - - let index_bytes = mesh.get_index_buffer_bytes(IndexFormat::Uint16).unwrap(); - let index_buffer = render_resources.create_buffer_with_data( - BufferInfo { - buffer_usage: BufferUsage::INDEX, - ..Default::default() - }, - &index_bytes, - ); - - render_resources.set_asset_resource( - *changed_mesh_handle, - vertex_buffer, - VERTEX_BUFFER_ASSET_INDEX, - ); - render_resources.set_asset_resource( - *changed_mesh_handle, - index_buffer, - INDEX_BUFFER_ASSET_INDEX, - ); - } + AssetEvent::Modified { handle } => { + changed_meshes.insert(*handle); + remove_current_mesh_resources(render_resources, *handle); } - - // TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target - for (handle, mut renderable) in query.iter_mut(world) { - if let Some(mesh) = meshes.get(&handle) { - renderable - .render_resource_assignments - .pipeline_specialization - .primitive_topology = mesh.primitive_topology; - } - - if let Some(vertex_buffer) = - render_resources.get_asset_resource(*handle, VERTEX_BUFFER_ASSET_INDEX) - { - let index_buffer = - render_resources.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX); - - renderable.render_resource_assignments.set_vertex_buffer( - "Vertex", - vertex_buffer, - index_buffer, - ); - } + AssetEvent::Removed { handle } => { + remove_current_mesh_resources(render_resources, *handle); + // if mesh was modified and removed in the same update, ignore the modification + // events are ordered so future modification events are ok + changed_meshes.remove(handle); } - }, - ) + } + } + + for changed_mesh_handle in changed_meshes.iter() { + if let Some(mesh) = meshes.get(changed_mesh_handle) { + let vertex_bytes = mesh + .get_vertex_buffer_bytes(&vertex_buffer_descriptor) + .unwrap(); + // TODO: use a staging buffer here + let vertex_buffer = render_resources.create_buffer_with_data( + BufferInfo { + buffer_usage: BufferUsage::VERTEX, + ..Default::default() + }, + &vertex_bytes, + ); + + let index_bytes = mesh.get_index_buffer_bytes(IndexFormat::Uint16).unwrap(); + let index_buffer = render_resources.create_buffer_with_data( + BufferInfo { + buffer_usage: BufferUsage::INDEX, + ..Default::default() + }, + &index_bytes, + ); + + render_resources.set_asset_resource( + *changed_mesh_handle, + vertex_buffer, + VERTEX_BUFFER_ASSET_INDEX, + ); + render_resources.set_asset_resource( + *changed_mesh_handle, + index_buffer, + INDEX_BUFFER_ASSET_INDEX, + ); + } + } + + // TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target + for (handle, mut renderable) in query.iter_mut(world) { + if let Some(mesh) = meshes.get(&handle) { + renderable + .render_resource_assignments + .pipeline_specialization + .primitive_topology = mesh.primitive_topology; + } + + if let Some(vertex_buffer) = + render_resources.get_asset_resource(*handle, VERTEX_BUFFER_ASSET_INDEX) + { + let index_buffer = + render_resources.get_asset_resource(*handle, INDEX_BUFFER_ASSET_INDEX); + + renderable.render_resource_assignments.set_vertex_buffer( + "Vertex", + vertex_buffer, + index_buffer, + ); + } + } + }) + .system() } #[cfg(test)] diff --git a/crates/bevy_wgpu/src/renderer/systems.rs b/crates/bevy_wgpu/src/renderer/systems.rs index 212db4b86e..8bbb0202d6 100644 --- a/crates/bevy_wgpu/src/renderer/systems.rs +++ b/crates/bevy_wgpu/src/renderer/systems.rs @@ -6,6 +6,45 @@ use bevy_render::{ }; use legion::prelude::*; +// TODO: replace with system_fn once configurable "archetype access" is sorted out +// pub fn render_resource_sets_system( +// world: &mut SubWorld, +// pipelines: Res>, +// pipeline_compiler: Res, +// pipeline_assignments: Res, +// entity_render_resource_assignments: Res, +// query: &mut Query>, // gives SubWorld write access to Renderable +// ) { +// // PERF: consider doing a par-iter over all renderable components so this can be parallelized +// for compiled_pipeline_handle in pipeline_compiler.iter_all_compiled_pipelines() { +// if let Some(compiled_pipeline_assignments) = pipeline_assignments +// .assignments +// .get(compiled_pipeline_handle) +// { +// let compiled_pipeline = pipelines.get(compiled_pipeline_handle).unwrap(); +// let pipeline_layout = compiled_pipeline.get_layout().unwrap(); + +// for assignment_id in compiled_pipeline_assignments.iter() { +// let entity = entity_render_resource_assignments +// .get(*assignment_id) +// .unwrap(); +// let mut renderable = world.get_component_mut::(*entity).unwrap(); +// if !renderable.is_visible || renderable.is_instanced { +// continue; +// } + +// for bind_group in pipeline_layout.bind_groups.iter() { +// renderable +// .render_resource_assignments +// .update_render_resource_set_id(bind_group); +// } +// } +// } +// } +// } + + + pub fn render_resource_sets_system() -> Box { SystemBuilder::new("update_render_resource_sets") .read_resource::>()