diff --git a/pipelined/bevy_core_pipeline/src/clear_pass.rs b/pipelined/bevy_core_pipeline/src/clear_pass.rs new file mode 100644 index 0000000000000..8ce2e66cfe2a0 --- /dev/null +++ b/pipelined/bevy_core_pipeline/src/clear_pass.rs @@ -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>, +} + +impl ClearPassNode { + pub fn new(world: &mut World) -> Self { + Self { + query: QueryState::new(world), + } + } +} + +impl Node for ClearPassNode { + fn input(&self) -> Vec { + 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::().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(()) + } +} diff --git a/pipelined/bevy_core_pipeline/src/clear_pass_driver.rs b/pipelined/bevy_core_pipeline/src/clear_pass_driver.rs new file mode 100644 index 0000000000000..d70b36ec50f39 --- /dev/null +++ b/pipelined/bevy_core_pipeline/src/clear_pass_driver.rs @@ -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(()) + } +} diff --git a/pipelined/bevy_core_pipeline/src/lib.rs b/pipelined/bevy_core_pipeline/src/lib.rs index 7da6c588875f5..36fe347685d4a 100644 --- a/pipelined/bevy_core_pipeline/src/lib.rs +++ b/pipelined/bevy_core_pipeline/src/lib.rs @@ -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::) .add_system_to_stage(RenderStage::PhaseSort, sort_phase_system::); + 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::().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(); } } diff --git a/pipelined/bevy_core_pipeline/src/main_pass_2d.rs b/pipelined/bevy_core_pipeline/src/main_pass_2d.rs index 86b1baa49e99c..9eec2e5ea4246 100644 --- a/pipelined/bevy_core_pipeline/src/main_pass_2d.rs +++ b/pipelined/bevy_core_pipeline/src/main_pass_2d.rs @@ -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::().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, }, }], diff --git a/pipelined/bevy_core_pipeline/src/main_pass_3d.rs b/pipelined/bevy_core_pipeline/src/main_pass_3d.rs index a539d6279d80a..617b89f512652 100644 --- a/pipelined/bevy_core_pipeline/src/main_pass_3d.rs +++ b/pipelined/bevy_core_pipeline/src/main_pass_3d.rs @@ -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::().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,