render graph 2: schedulers + window nodes
This commit is contained in:
		
							parent
							
								
									210a50e781
								
							
						
					
					
						commit
						5fec31b63c
					
				| @ -41,7 +41,7 @@ use self::{ | ||||
|     render_resource::{ | ||||
|         entity_render_resource_assignments_system, | ||||
|         resource_providers::{ | ||||
|             Camera2dResourceProvider, CameraResourceProvider, LightResourceProvider, | ||||
|             LightResourceProvider, | ||||
|             UniformResourceProvider, | ||||
|         }, | ||||
|         AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments, | ||||
| @ -50,12 +50,11 @@ use self::{ | ||||
|     texture::Texture, | ||||
| }; | ||||
| 
 | ||||
| use bevy_app::{stage, AppBuilder, AppPlugin, GetEventReader}; | ||||
| use bevy_app::{stage, AppBuilder, AppPlugin}; | ||||
| use bevy_asset::AssetStorage; | ||||
| use bevy_transform::prelude::LocalToWorld; | ||||
| use bevy_window::WindowResized; | ||||
| use render_resource::resource_providers::{CameraNode, mesh_resource_provider_system}; | ||||
| use render_graph_2::RenderGraph2; | ||||
| use render_resource::resource_providers::{mesh_resource_provider_system}; | ||||
| use render_graph_2::{nodes::{Camera2dNode, CameraNode}, RenderGraph2}; | ||||
| 
 | ||||
| pub static RENDER_RESOURCE_STAGE: &str = "render_resource"; | ||||
| pub static RENDER_STAGE: &str = "render"; | ||||
| @ -78,9 +77,6 @@ impl RenderPlugin { | ||||
|             .add_draw_target(AssignedBatchesDrawTarget::default()) | ||||
|             .add_draw_target(AssignedMeshesDrawTarget::default()) | ||||
|             .add_draw_target(UiDrawTarget::default()) | ||||
|             .add_resource_provider(Camera2dResourceProvider::new( | ||||
|                 resources.get_event_reader::<WindowResized>(), | ||||
|             )) | ||||
|             .add_resource_provider(LightResourceProvider::new(10)) | ||||
|             .add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true)) | ||||
|             .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)) | ||||
| @ -93,6 +89,7 @@ impl AppPlugin for RenderPlugin { | ||||
|     fn build(&self, app: &mut AppBuilder) { | ||||
|         let mut render_graph = RenderGraph2::default(); | ||||
|         render_graph.add_system_node(CameraNode::default(), app.resources_mut()); | ||||
|         render_graph.add_system_node(Camera2dNode::default(), app.resources_mut()); | ||||
|         let mut asset_batchers = AssetBatchers::default(); | ||||
|         asset_batchers.batch_types2::<Mesh, StandardMaterial>(); | ||||
|         app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE) | ||||
|  | ||||
| @ -1,3 +1,5 @@ | ||||
| pub mod nodes; | ||||
| 
 | ||||
| use crate::{ | ||||
|     render_resource::{RenderResource, ResourceInfo}, | ||||
|     renderer_2::RenderContext, | ||||
| @ -76,37 +78,124 @@ impl NodeId { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct ResourceBinding { | ||||
|     pub resource: Option<RenderResource>, | ||||
|     pub slot: ResourceSlot, | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct ResourceBindings { | ||||
|     bindings: Vec<ResourceBinding>, | ||||
| } | ||||
| 
 | ||||
| impl ResourceBindings { | ||||
|     pub fn set(&mut self, index: usize, resource: RenderResource) { | ||||
|         self.bindings[index].resource = Some(resource); | ||||
|     } | ||||
| 
 | ||||
|     pub fn set_named(&mut self, name: &str, resource: RenderResource) { | ||||
|         let binding = self | ||||
|             .bindings | ||||
|             .iter_mut() | ||||
|             .find(|b| b.slot.name == name) | ||||
|             .expect("Name not found"); | ||||
|         binding.resource = Some(resource); | ||||
|     } | ||||
| 
 | ||||
|     pub fn get(&self, index: usize) -> Option<RenderResource> { | ||||
|         self.bindings | ||||
|             .get(index) | ||||
|             .and_then(|binding| binding.resource) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_named(&self, name: &str) -> Option<RenderResource> { | ||||
|         self.bindings | ||||
|             .iter() | ||||
|             .find(|b| b.slot.name == name) | ||||
|             .and_then(|binding| binding.resource) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<&ResourceSlot> for ResourceBinding { | ||||
|     fn from(slot: &ResourceSlot) -> Self { | ||||
|         ResourceBinding { | ||||
|             resource: None, | ||||
|             slot: slot.clone(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<&[ResourceSlot]> for ResourceBindings { | ||||
|     fn from(slots: &[ResourceSlot]) -> Self { | ||||
|         ResourceBindings { | ||||
|             bindings: slots | ||||
|                 .iter() | ||||
|                 .map(|s| s.into()) | ||||
|                 .collect::<Vec<ResourceBinding>>(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct ResourceSlot { | ||||
|     name: Option<String>, | ||||
|     name: &'static str, | ||||
|     resource_type: ResourceInfo, | ||||
| } | ||||
| 
 | ||||
| pub struct ResourceSlotBinding { | ||||
|     resource: RenderResource, | ||||
| } | ||||
| 
 | ||||
| pub struct NodeDescriptor { | ||||
|     pub inputs: Vec<ResourceSlot>, | ||||
|     pub outputs: Vec<ResourceSlot>, | ||||
| impl ResourceSlot { | ||||
|     pub const fn new(name: &'static str, resource_type: ResourceInfo) -> Self { | ||||
|         ResourceSlot { | ||||
|             name, | ||||
|             resource_type, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait Node: Send + Sync + 'static { | ||||
|     fn descriptor(&self) -> &NodeDescriptor; | ||||
|     fn input(&self) -> &[ResourceSlot] { | ||||
|         &[] | ||||
|     } | ||||
| 
 | ||||
|     fn output(&self) -> &[ResourceSlot] { | ||||
|         &[] | ||||
|     } | ||||
| 
 | ||||
|     fn update( | ||||
|         &mut self, | ||||
|         world: &World, | ||||
|         resources: &Resources, | ||||
|         render_context: &mut dyn RenderContext, | ||||
|         input: &ResourceBindings, | ||||
|         output: &mut ResourceBindings, | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| pub struct NodeState { | ||||
|     pub node: Box<dyn Node>, | ||||
|     pub input: ResourceBindings, | ||||
|     pub output: ResourceBindings, | ||||
| } | ||||
| 
 | ||||
| impl NodeState { | ||||
|     pub fn new<T>(node: T) -> Self | ||||
|     where | ||||
|         T: Node, | ||||
|     { | ||||
|         NodeState { | ||||
|             input: ResourceBindings::from(node.input()), | ||||
|             output: ResourceBindings::from(node.output()), | ||||
|             node: Box::new(node), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait SystemNode: Node { | ||||
|     fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable>; | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct RenderGraph2 { | ||||
|     nodes: HashMap<NodeId, Box<dyn Node>>, | ||||
|     nodes: HashMap<NodeId, NodeState>, | ||||
|     new_systems: Vec<Box<dyn Schedulable>>, | ||||
|     system_executor: Option<Executor>, | ||||
| } | ||||
| @ -117,7 +206,7 @@ impl RenderGraph2 { | ||||
|         T: Node + 'static, | ||||
|     { | ||||
|         let id = NodeId::new(); | ||||
|         self.nodes.insert(id, Box::new(node)); | ||||
|         self.nodes.insert(id, NodeState::new(node)); | ||||
|         id | ||||
|     } | ||||
| 
 | ||||
| @ -127,14 +216,10 @@ impl RenderGraph2 { | ||||
|     { | ||||
|         let id = NodeId::new(); | ||||
|         self.new_systems.push(node.get_system(resources)); | ||||
|         self.nodes.insert(id, Box::new(node)); | ||||
|         self.nodes.insert(id, NodeState::new(node)); | ||||
|         id | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_schedule(&mut self) -> impl Iterator<Item = &mut Box<dyn Node>> { | ||||
|         self.nodes.values_mut() | ||||
|     } | ||||
| 
 | ||||
|     pub fn take_executor(&mut self) -> Option<Executor> { | ||||
|         // rebuild executor if there are new systems
 | ||||
|         if self.new_systems.len() > 0 { | ||||
| @ -157,3 +242,54 @@ impl RenderGraph2 { | ||||
|         self.system_executor = Some(executor); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct Stage<'a> { | ||||
|     ordered_jobs: Vec<OrderedJob<'a>>, | ||||
| } | ||||
| 
 | ||||
| impl<'a> Stage<'a> { | ||||
|     pub fn add(&mut self, job: OrderedJob<'a>) { | ||||
|         self.ordered_jobs.push(job); | ||||
|     } | ||||
| 
 | ||||
|     pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut OrderedJob<'a>> { | ||||
|         self.ordered_jobs.iter_mut() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct OrderedJob<'a> { | ||||
|     node_states: Vec<&'a mut NodeState>, | ||||
| } | ||||
| 
 | ||||
| impl<'a> OrderedJob<'a> { | ||||
|     pub fn add(&mut self, node_state: &'a mut NodeState) { | ||||
|         self.node_states.push(node_state); | ||||
|     } | ||||
| 
 | ||||
|     pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut &'a mut NodeState> { | ||||
|         self.node_states.iter_mut() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait RenderGraphScheduler { | ||||
|     fn get_stages<'a>(&mut self, render_graph: &'a mut RenderGraph2) -> Vec<Stage<'a>>; | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct LinearScheduler; | ||||
| 
 | ||||
| impl RenderGraphScheduler for LinearScheduler { | ||||
|     fn get_stages<'a>(&mut self, render_graph: &'a mut RenderGraph2) -> Vec<Stage<'a>> { | ||||
|         let mut stage = Stage::default(); | ||||
|         let mut job = OrderedJob::default(); | ||||
|         for node_state in render_graph.nodes.values_mut() { | ||||
|             job.add(node_state);        
 | ||||
|         } | ||||
| 
 | ||||
|         stage.ordered_jobs.push(job); | ||||
| 
 | ||||
|         vec![stage] | ||||
|     } | ||||
| } | ||||
							
								
								
									
										100
									
								
								bevy_render/src/render_graph_2/nodes/camera2d_node.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								bevy_render/src/render_graph_2/nodes/camera2d_node.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | ||||
| use bevy_app::{Events, GetEventReader}; | ||||
| use bevy_window::WindowResized; | ||||
| 
 | ||||
| use crate::{ | ||||
|     camera::{ActiveCamera2d, Camera}, | ||||
|     render_graph_2::{CommandQueue, Node, SystemNode, ResourceBindings}, | ||||
|     render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, | ||||
|     renderer_2::{GlobalRenderResourceContext, RenderContext}, | ||||
| }; | ||||
| 
 | ||||
| use bevy_transform::components::LocalToWorld; | ||||
| use legion::prelude::*; | ||||
| use zerocopy::AsBytes; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct Camera2dNode { | ||||
|     command_queue: CommandQueue, | ||||
| } | ||||
| 
 | ||||
| impl Node for Camera2dNode { | ||||
|     fn update( | ||||
|         &mut self, | ||||
|         _world: &World, | ||||
|         _resources: &Resources, | ||||
|         render_context: &mut dyn RenderContext, | ||||
|         _input: &ResourceBindings, | ||||
|         _output: &mut ResourceBindings, | ||||
|     ) { | ||||
|         self.command_queue.execute(render_context); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl SystemNode for Camera2dNode { | ||||
|     fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> { | ||||
|         let mut camera_buffer = None; | ||||
|         let mut tmp_buffer = None; | ||||
|         let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>(); | ||||
|         let mut command_queue = self.command_queue.clone(); | ||||
|         SystemBuilder::new("camera_resource_provider") | ||||
|             .read_resource::<GlobalRenderResourceContext>() | ||||
|             // TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
 | ||||
|             .write_resource::<RenderResourceAssignments>() | ||||
|             .read_resource::<Events<WindowResized>>() | ||||
|             .with_query(<(Read<Camera>, Read<LocalToWorld>, Read<ActiveCamera2d>)>::query()) | ||||
|             .build( | ||||
|                 move |_, | ||||
|                       world, | ||||
|                       ( | ||||
|                     render_resource_context, | ||||
|                     ref mut render_resource_assignments, | ||||
|                     window_resized_events, | ||||
|                 ), | ||||
|                       query| { | ||||
|                     let render_resources = &render_resource_context.context; | ||||
|                     if camera_buffer.is_none() { | ||||
|                         let buffer = render_resources.create_buffer(BufferInfo { | ||||
|                             size: std::mem::size_of::<[[f32; 4]; 4]>(), | ||||
|                             buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, | ||||
|                             ..Default::default() | ||||
|                         }); | ||||
|                         render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer); | ||||
|                         camera_buffer = Some(buffer); | ||||
|                     } | ||||
| 
 | ||||
|                     let primary_window_resized_event = window_resized_events | ||||
|                         .find_latest(&mut window_resized_event_reader, |event| event.is_primary); | ||||
|                     if let Some(_) = primary_window_resized_event { | ||||
|                         let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); | ||||
|                         for (camera, local_to_world, _) in query.iter(world) { | ||||
|                             let camera_matrix: [[f32; 4]; 4] = | ||||
|                                 (camera.view_matrix * local_to_world.0).to_cols_array_2d(); | ||||
| 
 | ||||
|                             if let Some(old_tmp_buffer) = tmp_buffer { | ||||
|                                 render_resources.remove_buffer(old_tmp_buffer); | ||||
|                             } | ||||
| 
 | ||||
|                             tmp_buffer = Some(render_resources.create_buffer_mapped( | ||||
|                                 BufferInfo { | ||||
|                                     size: matrix_size, | ||||
|                                     buffer_usage: BufferUsage::COPY_SRC, | ||||
|                                     ..Default::default() | ||||
|                                 }, | ||||
|                                 &mut |data, _renderer| { | ||||
|                                     data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes()); | ||||
|                                 }, | ||||
|                             )); | ||||
| 
 | ||||
|                             command_queue.copy_buffer_to_buffer( | ||||
|                                 tmp_buffer.unwrap(), | ||||
|                                 0, | ||||
|                                 camera_buffer.unwrap(), | ||||
|                                 0, | ||||
|                                 matrix_size as u64, | ||||
|                             ); | ||||
|                         } | ||||
|                     } | ||||
|                 }, | ||||
|             ) | ||||
|     } | ||||
| } | ||||
| @ -1,7 +1,5 @@ | ||||
| use bevy_window::WindowResized; | ||||
| 
 | ||||
| use crate::{ | ||||
|     render_graph_2::{CommandQueue, Node, NodeDescriptor, SystemNode}, | ||||
|     render_graph_2::{CommandQueue, Node, SystemNode, ResourceBindings}, | ||||
|     render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, | ||||
|     renderer_2::{GlobalRenderResourceContext, RenderContext}, | ||||
|     ActiveCamera, Camera, | ||||
| @ -10,8 +8,8 @@ use crate::{ | ||||
| use bevy_app::{Events, GetEventReader}; | ||||
| use bevy_transform::prelude::*; | ||||
| use legion::prelude::*; | ||||
| use once_cell::sync::Lazy; | ||||
| use zerocopy::AsBytes; | ||||
| use bevy_window::WindowResized; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct CameraNode { | ||||
| @ -19,19 +17,13 @@ pub struct CameraNode { | ||||
| } | ||||
| 
 | ||||
| impl Node for CameraNode { | ||||
|     fn descriptor(&self) -> &NodeDescriptor { | ||||
|         static DESCRIPTOR: Lazy<NodeDescriptor> = Lazy::new(|| NodeDescriptor { | ||||
|             inputs: Vec::new(), | ||||
|             outputs: Vec::new(), | ||||
|         }); | ||||
|         &DESCRIPTOR | ||||
|     } | ||||
| 
 | ||||
|     fn update( | ||||
|         &mut self, | ||||
|         _world: &World, | ||||
|         _resources: &Resources, | ||||
|         render_context: &mut dyn RenderContext, | ||||
|         _input: &ResourceBindings, | ||||
|         _output: &mut ResourceBindings, | ||||
|     ) { | ||||
|         self.command_queue.execute(render_context); | ||||
|     } | ||||
							
								
								
									
										9
									
								
								bevy_render/src/render_graph_2/nodes/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								bevy_render/src/render_graph_2/nodes/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| mod camera_node; | ||||
| mod camera2d_node; | ||||
| mod window_texture_node; | ||||
| mod window_swapchain_node; | ||||
| 
 | ||||
| pub use camera_node::*; | ||||
| pub use camera2d_node::*; | ||||
| pub use window_texture_node::*; | ||||
| pub use window_swapchain_node::*; | ||||
| @ -0,0 +1,70 @@ | ||||
| use crate::{ | ||||
|     render_graph_2::{Node, ResourceBindings, ResourceSlot}, | ||||
|     render_resource::{RenderResource, ResourceInfo}, | ||||
|     renderer_2::RenderContext, | ||||
|     texture::TextureDescriptor, | ||||
| }; | ||||
| use bevy_app::{EventReader, Events}; | ||||
| use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; | ||||
| use legion::prelude::*; | ||||
| 
 | ||||
| pub struct WindowSwapChainNode { | ||||
|     window_id: WindowId, | ||||
|     use_primary_window: bool, | ||||
|     window_resized_event_reader: EventReader<WindowResized>, | ||||
|     window_created_event_reader: EventReader<WindowCreated>, | ||||
|     swap_chain_resource: Option<RenderResource>, | ||||
| } | ||||
| 
 | ||||
| impl Node for WindowSwapChainNode { | ||||
|     fn output(&self) -> &[ResourceSlot] { | ||||
|         static OUTPUT: &[ResourceSlot] = &[ResourceSlot::new( | ||||
|             "swapchain_texture", | ||||
|             ResourceInfo::Texture, | ||||
|         )]; | ||||
|         OUTPUT | ||||
|     } | ||||
| 
 | ||||
|     fn update( | ||||
|         &mut self, | ||||
|         _world: &World, | ||||
|         resources: &Resources, | ||||
|         render_context: &mut dyn RenderContext, | ||||
|         _input: &ResourceBindings, | ||||
|         output: &mut ResourceBindings, | ||||
|     ) { | ||||
|         const WINDOW_TEXTURE: usize = 0; | ||||
|         let window_created_events = resources.get::<Events<WindowCreated>>().unwrap(); | ||||
|         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||
|         let windows = resources.get::<Windows>().unwrap(); | ||||
| 
 | ||||
|         let render_resources = render_context.resources_mut(); | ||||
|         let window = if self.use_primary_window { | ||||
|             windows.get_primary().expect("No primary window exists") | ||||
|         } else { | ||||
|             windows | ||||
|             .get(self.window_id) | ||||
|             .expect("Received window resized event for non-existent window") | ||||
|         }; | ||||
| 
 | ||||
|         // create window swapchain
 | ||||
|         if let Some(_) = window_created_events | ||||
|             .find_latest(&mut self.window_created_event_reader, |e| { | ||||
|                 e.id == window.id | ||||
|             }) | ||||
|         { | ||||
|             render_resources.create_swap_chain(window); | ||||
|         } | ||||
| 
 | ||||
|         // resize window swapchain
 | ||||
|         if let Some(_) = window_resized_events | ||||
|             .find_latest(&mut self.window_resized_event_reader, |e| { | ||||
|                 e.id == window.id | ||||
|             }) | ||||
|         { | ||||
|             render_resources.create_swap_chain(window); | ||||
|         } | ||||
| 
 | ||||
|         output.set(WINDOW_TEXTURE, self.swap_chain_resource.unwrap()); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								bevy_render/src/render_graph_2/nodes/window_texture_node.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								bevy_render/src/render_graph_2/nodes/window_texture_node.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| use crate::{ | ||||
|     render_graph_2::{Node, ResourceBindings, ResourceSlot}, | ||||
|     render_resource::ResourceInfo, | ||||
|     renderer_2::RenderContext, | ||||
|     texture::TextureDescriptor, | ||||
| }; | ||||
| use bevy_app::{EventReader, Events}; | ||||
| use bevy_window::WindowResized; | ||||
| use legion::prelude::*; | ||||
| 
 | ||||
| pub struct WindowTextureNode { | ||||
|     pub descriptor: TextureDescriptor, | ||||
|     window_resized_event_reader: EventReader<WindowResized>, | ||||
| } | ||||
| 
 | ||||
| impl Node for WindowTextureNode { | ||||
|     fn output(&self) -> &[ResourceSlot] { | ||||
|         static OUTPUT: &[ResourceSlot] = | ||||
|             &[ResourceSlot::new("window_texture", ResourceInfo::Texture)]; | ||||
|         OUTPUT | ||||
|     } | ||||
| 
 | ||||
|     fn update( | ||||
|         &mut self, | ||||
|         _world: &World, | ||||
|         resources: &Resources, | ||||
|         render_context: &mut dyn RenderContext, | ||||
|         _input: &ResourceBindings, | ||||
|         output: &mut ResourceBindings, | ||||
|     ) { | ||||
|         const WINDOW_TEXTURE: usize = 0; | ||||
|         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||
|         if let Some(event) = window_resized_events.latest(&mut self.window_resized_event_reader) { | ||||
|             let render_resources = render_context.resources_mut(); | ||||
|             if let Some(old_texture) = output.get(WINDOW_TEXTURE) { | ||||
|                 render_resources.remove_texture(old_texture); | ||||
|             } | ||||
| 
 | ||||
|             self.descriptor.size.width = event.width; | ||||
|             self.descriptor.size.height = event.height; | ||||
|             let texture_resource = render_resources.create_texture(&self.descriptor); | ||||
|             output.set(WINDOW_TEXTURE, texture_resource); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,91 +0,0 @@ | ||||
| use bevy_app::{EventReader, Events}; | ||||
| use bevy_window::WindowResized; | ||||
| 
 | ||||
| use crate::{ | ||||
|     camera::{ActiveCamera2d, Camera}, | ||||
|     render_resource::{ | ||||
|         resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, | ||||
|         ResourceProvider, | ||||
|     }, | ||||
|     renderer_2::RenderContext, | ||||
| }; | ||||
| 
 | ||||
| use legion::prelude::*; | ||||
| use zerocopy::AsBytes; | ||||
| 
 | ||||
| pub struct Camera2dResourceProvider { | ||||
|     pub camera_buffer: Option<RenderResource>, | ||||
|     pub tmp_buffer: Option<RenderResource>, | ||||
|     pub window_resized_event_reader: EventReader<WindowResized>, | ||||
| } | ||||
| 
 | ||||
| impl Camera2dResourceProvider { | ||||
|     pub fn new(window_resized_event_reader: EventReader<WindowResized>) -> Self { | ||||
|         Camera2dResourceProvider { | ||||
|             camera_buffer: None, | ||||
|             tmp_buffer: None, | ||||
|             window_resized_event_reader, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ResourceProvider for Camera2dResourceProvider { | ||||
|     fn initialize( | ||||
|         &mut self, | ||||
|         render_context: &mut dyn RenderContext, | ||||
|         _world: &mut World, | ||||
|         resources: &Resources, | ||||
|     ) { | ||||
|         let buffer = render_context.resources_mut().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::<RenderResourceAssignments>().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: &World, | ||||
|         resources: &Resources, | ||||
|     ) { | ||||
|         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||
|         let primary_window_resized_event = window_resized_events | ||||
|             .find_latest(&mut self.window_resized_event_reader, |event| event.is_primary); | ||||
| 
 | ||||
|         if let Some(_) = primary_window_resized_event { | ||||
|             let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); | ||||
|             for (camera, _) in <(Read<Camera>, Read<ActiveCamera2d>)>::query().iter(world) { | ||||
|                 let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d(); | ||||
| 
 | ||||
|                 if let Some(old_tmp_buffer) = self.tmp_buffer { | ||||
|                     render_context.resources_mut().remove_buffer(old_tmp_buffer); | ||||
|                 } | ||||
| 
 | ||||
|                 self.tmp_buffer = Some(render_context.resources_mut().create_buffer_mapped( | ||||
|                     BufferInfo { | ||||
|                         size: matrix_size, | ||||
|                         buffer_usage: BufferUsage::COPY_SRC, | ||||
|                         ..Default::default() | ||||
|                     }, | ||||
|                     &mut |data, _renderer| { | ||||
|                         data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes()); | ||||
|                     }, | ||||
|                 )); | ||||
| 
 | ||||
|                 render_context.copy_buffer_to_buffer( | ||||
|                     self.tmp_buffer.unwrap(), | ||||
|                     0, | ||||
|                     self.camera_buffer.unwrap(), | ||||
|                     0, | ||||
|                     matrix_size as u64, | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,11 +1,50 @@ | ||||
| use crate::{ | ||||
|     render_resource::{RenderResourceAssignments, ResourceProvider}, | ||||
|     render_graph_2::{Node, ResourceBindings, ResourceSlot}, | ||||
|     render_resource::{RenderResourceAssignments, ResourceInfo, ResourceProvider}, | ||||
|     renderer_2::RenderContext, | ||||
|     texture::TextureDescriptor, | ||||
| }; | ||||
| use bevy_window::Windows; | ||||
| use bevy_app::{EventReader, Events}; | ||||
| use bevy_window::{WindowResized, Windows}; | ||||
| use legion::prelude::*; | ||||
| 
 | ||||
| pub struct WindowTextureNode { | ||||
|     pub name: String, | ||||
|     pub descriptor: TextureDescriptor, | ||||
|     pub window_resized_event_reader: EventReader<WindowResized>, | ||||
| } | ||||
| 
 | ||||
| impl Node for WindowTextureNode { | ||||
|     fn output(&self) -> &[ResourceSlot] { | ||||
|         static OUTPUT: &[ResourceSlot] = | ||||
|             &[ResourceSlot::new("window_texture", ResourceInfo::Texture)]; | ||||
|         OUTPUT | ||||
|     } | ||||
| 
 | ||||
|     fn update( | ||||
|         &mut self, | ||||
|         _world: &World, | ||||
|         resources: &Resources, | ||||
|         render_context: &mut dyn RenderContext, | ||||
|         _input: &ResourceBindings, | ||||
|         output: &mut ResourceBindings, | ||||
|     ) { | ||||
|         const WINDOW_TEXTURE: usize = 0; | ||||
|         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||
|         if let Some(event) = window_resized_events.latest(&mut self.window_resized_event_reader) { | ||||
|             let render_resources = render_context.resources_mut(); | ||||
|             if let Some(old_texture) = output.get(WINDOW_TEXTURE) { | ||||
|                 render_resources.remove_texture(old_texture); | ||||
|             } | ||||
| 
 | ||||
|             self.descriptor.size.width = event.width; | ||||
|             self.descriptor.size.height = event.height; | ||||
|             let texture_resource = render_resources.create_texture(&self.descriptor); | ||||
|             output.set(WINDOW_TEXTURE, texture_resource); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct FrameTextureResourceProvider { | ||||
|     pub name: String, | ||||
|     pub descriptor: TextureDescriptor, | ||||
|  | ||||
| @ -1,12 +1,8 @@ | ||||
| mod camera2d_resource_provider; | ||||
| mod camera_resource_provider; | ||||
| mod frame_texture_resource_provider; | ||||
| mod light_resource_provider; | ||||
| mod mesh_resource_provider; | ||||
| mod uniform_resource_provider; | ||||
| 
 | ||||
| pub use camera2d_resource_provider::*; | ||||
| pub use camera_resource_provider::*; | ||||
| pub use frame_texture_resource_provider::*; | ||||
| pub use light_resource_provider::*; | ||||
| pub use mesh_resource_provider::*; | ||||
|  | ||||
| @ -1,46 +1,46 @@ | ||||
| #![feature(test)] | ||||
| // #![feature(test)]
 | ||||
| 
 | ||||
| extern crate test; | ||||
| // extern crate test;
 | ||||
| 
 | ||||
| use legion::prelude::*; | ||||
| use legion_transform::{local_to_world_system, prelude::*}; | ||||
| use test::Bencher; | ||||
| // use legion::prelude::*;
 | ||||
| // use bevy_transform::{local_to_world_system, prelude::*};
 | ||||
| // use test::Bencher;
 | ||||
| 
 | ||||
| #[bench] | ||||
| fn local_to_world_update_without_change(b: &mut Bencher) { | ||||
|     let _ = env_logger::builder().is_test(true).try_init(); | ||||
| // #[bench]
 | ||||
| // fn local_to_world_update_without_change(b: &mut Bencher) {
 | ||||
| //     let _ = env_logger::builder().is_test(true).try_init();
 | ||||
| 
 | ||||
|     let mut world = Universe::new().create_world(); | ||||
|     let system = local_to_world_system::build(&mut world); | ||||
| //     let mut world = Universe::new().create_world();
 | ||||
| //     let system = local_to_world_system::build(&mut world);
 | ||||
| 
 | ||||
|     let ltw = LocalToWorld::identity(); | ||||
|     let t = Translation::new(1.0, 2.0, 3.0); | ||||
|     let r = Rotation::from_euler_angles(1.0, 2.0, 3.0); | ||||
|     let s = Scale(2.0); | ||||
|     let nus = NonUniformScale::new(1.0, 2.0, 3.0); | ||||
| //     let ltw = LocalToWorld::identity();
 | ||||
| //     let t = Translation::new(1.0, 2.0, 3.0);
 | ||||
| //     let r = Rotation::from_euler_angles(1.0, 2.0, 3.0);
 | ||||
| //     let s = Scale(2.0);
 | ||||
| //     let nus = NonUniformScale::new(1.0, 2.0, 3.0);
 | ||||
| 
 | ||||
|     // Add N of every combination of transform types.
 | ||||
|     let n = 1000; | ||||
|     let _translation = *world.insert((), vec![(ltw, t); n]).first().unwrap(); | ||||
|     let _rotation = *world.insert((), vec![(ltw, r); n]).first().unwrap(); | ||||
|     let _scale = *world.insert((), vec![(ltw, s); n]).first().unwrap(); | ||||
|     let _non_uniform_scale = *world.insert((), vec![(ltw, nus); n]).first().unwrap(); | ||||
|     let _translation_and_rotation = *world.insert((), vec![(ltw, t, r); n]).first().unwrap(); | ||||
|     let _translation_and_scale = *world.insert((), vec![(ltw, t, s); n]).first().unwrap(); | ||||
|     let _translation_and_nus = *world.insert((), vec![(ltw, t, nus); n]).first().unwrap(); | ||||
|     let _rotation_scale = *world.insert((), vec![(ltw, r, s); n]).first().unwrap(); | ||||
|     let _rotation_nus = *world.insert((), vec![(ltw, r, nus); n]).first().unwrap(); | ||||
|     let _translation_rotation_scale = *world.insert((), vec![(ltw, t, r, s); n]).first().unwrap(); | ||||
|     let _translation_rotation_nus = *world.insert((), vec![(ltw, t, r, nus); n]).first().unwrap(); | ||||
| //     // Add N of every combination of transform types.
 | ||||
| //     let n = 1000;
 | ||||
| //     let _translation = *world.insert((), vec![(ltw, t); n]).first().unwrap();
 | ||||
| //     let _rotation = *world.insert((), vec![(ltw, r); n]).first().unwrap();
 | ||||
| //     let _scale = *world.insert((), vec![(ltw, s); n]).first().unwrap();
 | ||||
| //     let _non_uniform_scale = *world.insert((), vec![(ltw, nus); n]).first().unwrap();
 | ||||
| //     let _translation_and_rotation = *world.insert((), vec![(ltw, t, r); n]).first().unwrap();
 | ||||
| //     let _translation_and_scale = *world.insert((), vec![(ltw, t, s); n]).first().unwrap();
 | ||||
| //     let _translation_and_nus = *world.insert((), vec![(ltw, t, nus); n]).first().unwrap();
 | ||||
| //     let _rotation_scale = *world.insert((), vec![(ltw, r, s); n]).first().unwrap();
 | ||||
| //     let _rotation_nus = *world.insert((), vec![(ltw, r, nus); n]).first().unwrap();
 | ||||
| //     let _translation_rotation_scale = *world.insert((), vec![(ltw, t, r, s); n]).first().unwrap();
 | ||||
| //     let _translation_rotation_nus = *world.insert((), vec![(ltw, t, r, nus); n]).first().unwrap();
 | ||||
| 
 | ||||
|     // Run the system once outside the test (which should compute everything and it shouldn't be
 | ||||
|     // touched again).
 | ||||
|     system.run(&mut world); | ||||
|     system.command_buffer_mut().write(&mut world); | ||||
| //     // Run the system once outside the test (which should compute everything and it shouldn't be
 | ||||
| //     // touched again).
 | ||||
| //     system.run(&mut world);
 | ||||
| //     system.command_buffer_mut().write(&mut world);
 | ||||
| 
 | ||||
|     // Then time the already-computed updates.
 | ||||
|     b.iter(|| { | ||||
|         system.run(&mut world); | ||||
|         system.command_buffer_mut().write(&mut world); | ||||
|     }); | ||||
| } | ||||
| //     // Then time the already-computed updates.
 | ||||
| //     b.iter(|| {
 | ||||
| //         system.run(&mut world);
 | ||||
| //         system.command_buffer_mut().write(&mut world);
 | ||||
| //     });
 | ||||
| // }
 | ||||
|  | ||||
| @ -6,7 +6,7 @@ use bevy_asset::AssetStorage; | ||||
| use bevy_render::{ | ||||
|     pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor}, | ||||
|     render_graph::RenderGraph, | ||||
|     render_graph_2::RenderGraph2, | ||||
|     render_graph_2::{LinearScheduler, RenderGraph2, RenderGraphScheduler}, | ||||
|     render_resource::RenderResourceAssignments, | ||||
|     renderer_2::{GlobalRenderResourceContext, RenderContext, RenderResourceContext}, | ||||
| }; | ||||
| @ -245,10 +245,15 @@ impl WgpuRenderer { | ||||
|             .context | ||||
|             .downcast_mut::<WgpuRenderResourceContext>() | ||||
|             .unwrap(); | ||||
|         let mut linear_scheduler = LinearScheduler::default(); | ||||
|         let mut render_context = | ||||
|             WgpuRenderContext::new(self.device.clone(), render_resource_context.clone()); | ||||
|         for node in render_graph.get_schedule() { | ||||
|             node.update(world, resources, &mut render_context); | ||||
|         for mut stage in linear_scheduler.get_stages(&mut render_graph) { | ||||
|             for job in stage.iter_mut() { | ||||
|                 for node_state in job.iter_mut() { | ||||
|                     node_state.node.update(world, resources, &mut render_context, &node_state.input, &mut node_state.output); | ||||
|                 } 
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let command_buffer = render_context.finish(); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson