From 8a53ba523b4f4761fd70881a91696d9b7166c6f7 Mon Sep 17 00:00:00 2001 From: KirmesBude Date: Fri, 26 Nov 2021 19:59:49 +0100 Subject: [PATCH 1/3] issue-3190: Add ClearPass and remove clearing from the main passes --- .../bevy_core_pipeline/src/clear_pass.rs | 78 +++++++++++++++++++ pipelined/bevy_core_pipeline/src/lib.rs | 10 +++ .../bevy_core_pipeline/src/main_pass_2d.rs | 6 +- .../bevy_core_pipeline/src/main_pass_3d.rs | 12 ++- 4 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 pipelined/bevy_core_pipeline/src/clear_pass.rs 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..b406b823dc844 --- /dev/null +++ b/pipelined/bevy_core_pipeline/src/clear_pass.rs @@ -0,0 +1,78 @@ +use crate::ClearColor; +use bevy_ecs::prelude::*; +use bevy_render2::{ + camera::{CameraPlugin, ExtractedCameraNames}, + 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> { + let extracted_cameras = world.get_resource::().unwrap(); + let view_entities: Vec<&Entity> = extracted_cameras + .entities + .iter() + .filter(|(name, _)| { + name.as_str() == CameraPlugin::CAMERA_2D || name.as_str() == CameraPlugin::CAMERA_3D + }) + .map(|(_, entity)| entity) + .collect(); + + for view_entity in view_entities { + let (target, depth) = self + .query + .get_manual(world, *view_entity) + .expect("view entity should exist"); + let clear_color = world.get_resource::().unwrap(); + let pass_descriptor = RenderPassDescriptor { + label: Some(crate::node::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, + // NOTE: The opaque main pass clears and writes to the depth buffer. + 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/lib.rs b/pipelined/bevy_core_pipeline/src/lib.rs index 7da6c588875f5..ef6f8c4856da3 100644 --- a/pipelined/bevy_core_pipeline/src/lib.rs +++ b/pipelined/bevy_core_pipeline/src/lib.rs @@ -1,3 +1,4 @@ +mod clear_pass; mod main_pass_2d; mod main_pass_3d; mod main_pass_driver; @@ -24,6 +25,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 +45,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: &str = "clear_pass"; pub const VIEW: &str = "view"; } @@ -86,6 +90,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(); @@ -127,6 +132,11 @@ impl Plugin for CorePipelinePlugin { graph .add_node_edge(node::MAIN_PASS_DEPENDENCIES, node::MAIN_PASS_DRIVER) .unwrap(); + + graph.add_node(node::CLEAR_PASS, clear_pass_node); + graph + .add_node_edge(node::CLEAR_PASS, node::MAIN_PASS_DEPENDENCIES) + .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 b63bb80949b2b..812cc80a067db 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,22 @@ 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 - // buffer as well as writing to it. + // NOTE: The opaque pass loads the color buffer as well as overwriting it where appropriate. 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, From a137198ee405e530c56af5d44881dab915ed33c1 Mon Sep 17 00:00:00 2001 From: KirmesBude Date: Sat, 27 Nov 2021 20:11:33 +0100 Subject: [PATCH 2/3] issue-3190: Clear all views --- .../bevy_core_pipeline/src/clear_pass.rs | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/pipelined/bevy_core_pipeline/src/clear_pass.rs b/pipelined/bevy_core_pipeline/src/clear_pass.rs index b406b823dc844..90766eb1faaf4 100644 --- a/pipelined/bevy_core_pipeline/src/clear_pass.rs +++ b/pipelined/bevy_core_pipeline/src/clear_pass.rs @@ -1,7 +1,6 @@ use crate::ClearColor; use bevy_ecs::prelude::*; use bevy_render2::{ - camera::{CameraPlugin, ExtractedCameraNames}, render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo}, render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor}, renderer::RenderContext, @@ -35,21 +34,8 @@ impl Node for ClearPassNode { render_context: &mut RenderContext, world: &World, ) -> Result<(), NodeRunError> { - let extracted_cameras = world.get_resource::().unwrap(); - let view_entities: Vec<&Entity> = extracted_cameras - .entities - .iter() - .filter(|(name, _)| { - name.as_str() == CameraPlugin::CAMERA_2D || name.as_str() == CameraPlugin::CAMERA_3D - }) - .map(|(_, entity)| entity) - .collect(); - - for view_entity in view_entities { - let (target, depth) = self - .query - .get_manual(world, *view_entity) - .expect("view entity should exist"); + /* 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(crate::node::CLEAR_PASS), @@ -59,7 +45,6 @@ impl Node for ClearPassNode { })], depth_stencil_attachment: Some(RenderPassDepthStencilAttachment { view: &depth.view, - // NOTE: The opaque main pass clears and writes to the depth buffer. depth_ops: Some(Operations { load: LoadOp::Clear(0.0), store: true, @@ -67,7 +52,7 @@ impl Node for ClearPassNode { stencil_ops: None, }), }; - + render_context .command_encoder .begin_render_pass(&pass_descriptor); From 095c2a22b95f9084fda21c1f6a41bf43fada6c58 Mon Sep 17 00:00:00 2001 From: KirmesBude Date: Sat, 27 Nov 2021 20:30:51 +0100 Subject: [PATCH 3/3] issue-3190: Add SubGraph and a "Driver" Node for consistency --- .../bevy_core_pipeline/src/clear_pass.rs | 2 +- .../src/clear_pass_driver.rs | 20 ++++++++++++++++++ pipelined/bevy_core_pipeline/src/lib.rs | 21 +++++++++++++++---- 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 pipelined/bevy_core_pipeline/src/clear_pass_driver.rs diff --git a/pipelined/bevy_core_pipeline/src/clear_pass.rs b/pipelined/bevy_core_pipeline/src/clear_pass.rs index 90766eb1faaf4..8ce2e66cfe2a0 100644 --- a/pipelined/bevy_core_pipeline/src/clear_pass.rs +++ b/pipelined/bevy_core_pipeline/src/clear_pass.rs @@ -38,7 +38,7 @@ impl Node for ClearPassNode { for (target, depth) in self.query.iter_manual(world) { let clear_color = world.get_resource::().unwrap(); let pass_descriptor = RenderPassDescriptor { - label: Some(crate::node::CLEAR_PASS), + label: Some("clear_pass"), color_attachments: &[target.get_color_attachment(Operations { load: LoadOp::Clear(clear_color.0.into()), store: true, 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 ef6f8c4856da3..36fe347685d4a 100644 --- a/pipelined/bevy_core_pipeline/src/lib.rs +++ b/pipelined/bevy_core_pipeline/src/lib.rs @@ -1,8 +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::*; @@ -45,7 +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: &str = "clear_pass"; + pub const CLEAR_PASS_DRIVER: &str = "clear_pass_driver"; pub const VIEW: &str = "view"; } @@ -69,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; @@ -127,15 +137,18 @@ 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, clear_pass_node); + graph.add_node(node::CLEAR_PASS_DRIVER, ClearPassDriverNode); graph - .add_node_edge(node::CLEAR_PASS, node::MAIN_PASS_DEPENDENCIES) + .add_node_edge(node::CLEAR_PASS_DRIVER, node::MAIN_PASS_DRIVER) .unwrap(); } }