mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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
5 changed files with 114 additions and 9 deletions
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 a new issue