Add a separate ClearPass (#3209)
# Objective - Rendering before MainPass should be possible, so clearing needs to happen in an earlier pass. - Fixes #3190. ## Solution - I added a "Clear" SubGraph, a "ClearPassNode" Node, that clears the color and depth attachments of all views and a "ClearNodeDriver" Node, that schedules the "ClearPassNode" before MainPass. - Make sure that the 2d and 3d draw passes do not clear their attachments anymore. ### Notes - It works in the way, that with the current pipeline examples nothing should have changed in their behaviour - I would like to add an example that adds a pass inbetween ClearPass and MainPass, but I do not understand enough about the new render architecture to do that yet - Clears all attachment for all views: I do not know enough about rendering in general to say, whether there is a use case for not clearing - Does not solve #3043 as we still need Cameras/ViewTargets to clear.
This commit is contained in:
		
							parent
							
								
									4c91613ae6
								
							
						
					
					
						commit
						82c04f93f5
					
				
							
								
								
									
										63
									
								
								pipelined/bevy_core_pipeline/src/clear_pass.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								pipelined/bevy_core_pipeline/src/clear_pass.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| use crate::ClearColor; | ||||
| use bevy_ecs::prelude::*; | ||||
| use bevy_render2::{ | ||||
|     render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo}, | ||||
|     render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor}, | ||||
|     renderer::RenderContext, | ||||
|     view::{ExtractedView, ViewDepthTexture, ViewTarget}, | ||||
| }; | ||||
| 
 | ||||
| pub struct ClearPassNode { | ||||
|     query: QueryState<(&'static ViewTarget, &'static ViewDepthTexture), With<ExtractedView>>, | ||||
| } | ||||
| 
 | ||||
| impl ClearPassNode { | ||||
|     pub fn new(world: &mut World) -> Self { | ||||
|         Self { | ||||
|             query: QueryState::new(world), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Node for ClearPassNode { | ||||
|     fn input(&self) -> Vec<SlotInfo> { | ||||
|         vec![] | ||||
|     } | ||||
| 
 | ||||
|     fn update(&mut self, world: &mut World) { | ||||
|         self.query.update_archetypes(world); | ||||
|     } | ||||
| 
 | ||||
|     fn run( | ||||
|         &self, | ||||
|         _graph: &mut RenderGraphContext, | ||||
|         render_context: &mut RenderContext, | ||||
|         world: &World, | ||||
|     ) -> Result<(), NodeRunError> { | ||||
|         /* This gets all ViewTargets and ViewDepthTextures and clears its attachments */ | ||||
|         for (target, depth) in self.query.iter_manual(world) { | ||||
|             let clear_color = world.get_resource::<ClearColor>().unwrap(); | ||||
|             let pass_descriptor = RenderPassDescriptor { | ||||
|                 label: Some("clear_pass"), | ||||
|                 color_attachments: &[target.get_color_attachment(Operations { | ||||
|                     load: LoadOp::Clear(clear_color.0.into()), | ||||
|                     store: true, | ||||
|                 })], | ||||
|                 depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { | ||||
|                     view: &depth.view, | ||||
|                     depth_ops: Some(Operations { | ||||
|                         load: LoadOp::Clear(0.0), | ||||
|                         store: true, | ||||
|                     }), | ||||
|                     stencil_ops: None, | ||||
|                 }), | ||||
|             }; | ||||
| 
 | ||||
|             render_context | ||||
|                 .command_encoder | ||||
|                 .begin_render_pass(&pass_descriptor); | ||||
|         } | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								pipelined/bevy_core_pipeline/src/clear_pass_driver.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								pipelined/bevy_core_pipeline/src/clear_pass_driver.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| use bevy_ecs::world::World; | ||||
| use bevy_render2::{ | ||||
|     render_graph::{Node, NodeRunError, RenderGraphContext}, | ||||
|     renderer::RenderContext, | ||||
| }; | ||||
| 
 | ||||
| pub struct ClearPassDriverNode; | ||||
| 
 | ||||
| impl Node for ClearPassDriverNode { | ||||
|     fn run( | ||||
|         &self, | ||||
|         graph: &mut RenderGraphContext, | ||||
|         _render_context: &mut RenderContext, | ||||
|         _world: &World, | ||||
|     ) -> Result<(), NodeRunError> { | ||||
|         graph.run_sub_graph(crate::clear_graph::NAME, vec![])?; | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| @ -1,7 +1,11 @@ | ||||
| mod clear_pass; | ||||
| mod clear_pass_driver; | ||||
| mod main_pass_2d; | ||||
| mod main_pass_3d; | ||||
| mod main_pass_driver; | ||||
| 
 | ||||
| pub use clear_pass::*; | ||||
| pub use clear_pass_driver::*; | ||||
| pub use main_pass_2d::*; | ||||
| pub use main_pass_3d::*; | ||||
| pub use main_pass_driver::*; | ||||
| @ -24,6 +28,8 @@ use bevy_render2::{ | ||||
|     RenderApp, RenderStage, RenderWorld, | ||||
| }; | ||||
| 
 | ||||
| use crate::clear_pass::ClearPassNode; | ||||
| 
 | ||||
| /// Resource that configures the clear color
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct ClearColor(pub Color); | ||||
| @ -42,6 +48,7 @@ impl Default for ClearColor { | ||||
| pub mod node { | ||||
|     pub const MAIN_PASS_DEPENDENCIES: &str = "main_pass_dependencies"; | ||||
|     pub const MAIN_PASS_DRIVER: &str = "main_pass_driver"; | ||||
|     pub const CLEAR_PASS_DRIVER: &str = "clear_pass_driver"; | ||||
|     pub const VIEW: &str = "view"; | ||||
| } | ||||
| 
 | ||||
| @ -65,6 +72,13 @@ pub mod draw_3d_graph { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub mod clear_graph { | ||||
|     pub const NAME: &str = "clear"; | ||||
|     pub mod node { | ||||
|         pub const CLEAR_PASS: &str = "clear_pass"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct CorePipelinePlugin; | ||||
| 
 | ||||
| @ -86,6 +100,7 @@ impl Plugin for CorePipelinePlugin { | ||||
|             .add_system_to_stage(RenderStage::PhaseSort, sort_phase_system::<AlphaMask3d>) | ||||
|             .add_system_to_stage(RenderStage::PhaseSort, sort_phase_system::<Transparent3d>); | ||||
| 
 | ||||
|         let clear_pass_node = ClearPassNode::new(&mut render_app.world); | ||||
|         let pass_node_2d = MainPass2dNode::new(&mut render_app.world); | ||||
|         let pass_node_3d = MainPass3dNode::new(&mut render_app.world); | ||||
|         let mut graph = render_app.world.get_resource_mut::<RenderGraph>().unwrap(); | ||||
| @ -122,11 +137,19 @@ impl Plugin for CorePipelinePlugin { | ||||
|             .unwrap(); | ||||
|         graph.add_sub_graph(draw_3d_graph::NAME, draw_3d_graph); | ||||
| 
 | ||||
|         let mut clear_graph = RenderGraph::default(); | ||||
|         clear_graph.add_node(clear_graph::node::CLEAR_PASS, clear_pass_node); | ||||
|         graph.add_sub_graph(clear_graph::NAME, clear_graph); | ||||
| 
 | ||||
|         graph.add_node(node::MAIN_PASS_DEPENDENCIES, EmptyNode); | ||||
|         graph.add_node(node::MAIN_PASS_DRIVER, MainPassDriverNode); | ||||
|         graph | ||||
|             .add_node_edge(node::MAIN_PASS_DEPENDENCIES, node::MAIN_PASS_DRIVER) | ||||
|             .unwrap(); | ||||
|         graph.add_node(node::CLEAR_PASS_DRIVER, ClearPassDriverNode); | ||||
|         graph | ||||
|             .add_node_edge(node::CLEAR_PASS_DRIVER, node::MAIN_PASS_DRIVER) | ||||
|             .unwrap(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| use crate::{ClearColor, Transparent2d}; | ||||
| use crate::Transparent2d; | ||||
| use bevy_ecs::prelude::*; | ||||
| use bevy_render2::{ | ||||
|     render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, | ||||
| @ -43,14 +43,14 @@ impl Node for MainPass2dNode { | ||||
|             .query | ||||
|             .get_manual(world, view_entity) | ||||
|             .expect("view entity should exist"); | ||||
|         let clear_color = world.get_resource::<ClearColor>().unwrap(); | ||||
| 
 | ||||
|         let pass_descriptor = RenderPassDescriptor { | ||||
|             label: Some("main_pass_2d"), | ||||
|             color_attachments: &[RenderPassColorAttachment { | ||||
|                 view: &target.view, | ||||
|                 resolve_target: None, | ||||
|                 ops: Operations { | ||||
|                     load: LoadOp::Clear(clear_color.0.into()), | ||||
|                     load: LoadOp::Load, | ||||
|                     store: true, | ||||
|                 }, | ||||
|             }], | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| use crate::{AlphaMask3d, ClearColor, Opaque3d, Transparent3d}; | ||||
| use crate::{AlphaMask3d, Opaque3d, Transparent3d}; | ||||
| use bevy_ecs::prelude::*; | ||||
| use bevy_render2::{ | ||||
|     render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, | ||||
| @ -51,24 +51,23 @@ impl Node for MainPass3dNode { | ||||
|             .query | ||||
|             .get_manual(world, view_entity) | ||||
|             .expect("view entity should exist"); | ||||
|         let clear_color = world.get_resource::<ClearColor>().unwrap(); | ||||
| 
 | ||||
|         { | ||||
|             // Run the opaque pass, sorted front-to-back
 | ||||
|             // NOTE: Scoped to drop the mutable borrow of render_context
 | ||||
|             let pass_descriptor = RenderPassDescriptor { | ||||
|                 label: Some("main_opaque_pass_3d"), | ||||
|                 // NOTE: The opaque pass clears and initializes the color
 | ||||
|                 // NOTE: The opaque pass loads the color
 | ||||
|                 // buffer as well as writing to it.
 | ||||
|                 color_attachments: &[target.get_color_attachment(Operations { | ||||
|                     load: LoadOp::Clear(clear_color.0.into()), | ||||
|                     load: LoadOp::Load, | ||||
|                     store: true, | ||||
|                 })], | ||||
|                 depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { | ||||
|                     view: &depth.view, | ||||
|                     // NOTE: The opaque main pass clears and writes to the depth buffer.
 | ||||
|                     // NOTE: The opaque main pass loads the depth buffer and possibly overwrites it
 | ||||
|                     depth_ops: Some(Operations { | ||||
|                         load: LoadOp::Clear(0.0), | ||||
|                         load: LoadOp::Load, | ||||
|                         store: true, | ||||
|                     }), | ||||
|                     stencil_ops: None, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Bude
						Bude