Use RenderGraphApp in more places (#8298)

# Objective

- RenderGraphExt was merged, but only used in limited situations

## Solution

- Fix some remaining issues with the existing api
- Use the new api in the main pass and mass writeback
- Add CORE_2D and CORE_3D constant to make render_graph code shorter
This commit is contained in:
IceSentry 2023-04-05 16:57:56 -04:00 committed by GitHub
parent 0a17751d16
commit c70776b3cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 160 additions and 152 deletions

View File

@ -4,7 +4,10 @@ mod upsampling_pipeline;
pub use settings::{BloomCompositeMode, BloomPrefilterSettings, BloomSettings}; pub use settings::{BloomCompositeMode, BloomPrefilterSettings, BloomSettings};
use crate::{core_2d, core_3d}; use crate::{
core_2d::{self, CORE_2D},
core_3d::{self, CORE_3D},
};
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, HandleUntyped}; use bevy_asset::{load_internal_asset, HandleUntyped};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
@ -73,9 +76,9 @@ impl Plugin for BloomPlugin {
), ),
) )
// Add bloom to the 3d render graph // Add bloom to the 3d render graph
.add_render_graph_node::<BloomNode>(core_3d::graph::NAME, core_3d::graph::node::BLOOM) .add_render_graph_node::<BloomNode>(CORE_3D, core_3d::graph::node::BLOOM)
.add_render_graph_edges( .add_render_graph_edges(
core_3d::graph::NAME, CORE_3D,
&[ &[
core_3d::graph::node::END_MAIN_PASS, core_3d::graph::node::END_MAIN_PASS,
core_3d::graph::node::BLOOM, core_3d::graph::node::BLOOM,
@ -83,9 +86,9 @@ impl Plugin for BloomPlugin {
], ],
) )
// Add bloom to the 2d render graph // Add bloom to the 2d render graph
.add_render_graph_node::<BloomNode>(core_2d::graph::NAME, core_2d::graph::node::BLOOM) .add_render_graph_node::<BloomNode>(CORE_2D, core_2d::graph::node::BLOOM)
.add_render_graph_edges( .add_render_graph_edges(
core_2d::graph::NAME, CORE_2D,
&[ &[
core_2d::graph::node::MAIN_PASS, core_2d::graph::node::MAIN_PASS,
core_2d::graph::node::BLOOM, core_2d::graph::node::BLOOM,

View File

@ -1,4 +1,8 @@
use crate::{core_2d, core_3d, fullscreen_vertex_shader::fullscreen_shader_vertex_state}; use crate::{
core_2d::{self, CORE_2D},
core_3d::{self, CORE_3D},
fullscreen_vertex_shader::fullscreen_shader_vertex_state,
};
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, HandleUntyped}; use bevy_asset::{load_internal_asset, HandleUntyped};
use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_ecs::{prelude::*, query::QueryItem};
@ -114,48 +118,37 @@ impl Plugin for CASPlugin {
render_app render_app
.init_resource::<CASPipeline>() .init_resource::<CASPipeline>()
.init_resource::<SpecializedRenderPipelines<CASPipeline>>() .init_resource::<SpecializedRenderPipelines<CASPipeline>>()
.add_systems(Render, prepare_cas_pipelines.in_set(RenderSet::Prepare)) .add_systems(Render, prepare_cas_pipelines.in_set(RenderSet::Prepare));
// 3d
.add_render_graph_node::<CASNode>( {
core_3d::graph::NAME, use core_3d::graph::node::*;
core_3d::graph::node::CONTRAST_ADAPTIVE_SHARPENING, render_app
) .add_render_graph_node::<CASNode>(CORE_3D, CONTRAST_ADAPTIVE_SHARPENING)
.add_render_graph_edge( .add_render_graph_edge(CORE_3D, TONEMAPPING, CONTRAST_ADAPTIVE_SHARPENING)
core_3d::graph::NAME, .add_render_graph_edges(
core_3d::graph::node::TONEMAPPING, CORE_3D,
core_3d::graph::node::CONTRAST_ADAPTIVE_SHARPENING, &[
) FXAA,
.add_render_graph_edge( CONTRAST_ADAPTIVE_SHARPENING,
core_3d::graph::NAME, END_MAIN_PASS_POST_PROCESSING,
core_3d::graph::node::FXAA, ],
core_3d::graph::node::CONTRAST_ADAPTIVE_SHARPENING,
)
.add_render_graph_edge(
core_3d::graph::NAME,
core_3d::graph::node::CONTRAST_ADAPTIVE_SHARPENING,
core_3d::graph::node::END_MAIN_PASS_POST_PROCESSING,
)
// 2d
.add_render_graph_node::<CASNode>(
core_2d::graph::NAME,
core_2d::graph::node::CONTRAST_ADAPTIVE_SHARPENING,
)
.add_render_graph_edge(
core_2d::graph::NAME,
core_2d::graph::node::TONEMAPPING,
core_2d::graph::node::CONTRAST_ADAPTIVE_SHARPENING,
)
.add_render_graph_edge(
core_2d::graph::NAME,
core_2d::graph::node::FXAA,
core_2d::graph::node::CONTRAST_ADAPTIVE_SHARPENING,
)
.add_render_graph_edge(
core_2d::graph::NAME,
core_2d::graph::node::CONTRAST_ADAPTIVE_SHARPENING,
core_2d::graph::node::END_MAIN_PASS_POST_PROCESSING,
); );
} }
{
use core_2d::graph::node::*;
render_app
.add_render_graph_node::<CASNode>(CORE_2D, CONTRAST_ADAPTIVE_SHARPENING)
.add_render_graph_edge(CORE_2D, TONEMAPPING, CONTRAST_ADAPTIVE_SHARPENING)
.add_render_graph_edges(
CORE_2D,
&[
FXAA,
CONTRAST_ADAPTIVE_SHARPENING,
END_MAIN_PASS_POST_PROCESSING,
],
);
}
}
} }
#[derive(Resource)] #[derive(Resource)]

View File

@ -26,8 +26,8 @@ pub struct MainPass2dNode {
>, >,
} }
impl MainPass2dNode { impl FromWorld for MainPass2dNode {
pub fn new(world: &mut World) -> Self { fn from_world(world: &mut World) -> Self {
Self { Self {
query: world.query_filtered(), query: world.query_filtered(),
} }

View File

@ -17,6 +17,7 @@ pub mod graph {
pub const END_MAIN_PASS_POST_PROCESSING: &str = "end_main_pass_post_processing"; pub const END_MAIN_PASS_POST_PROCESSING: &str = "end_main_pass_post_processing";
} }
} }
pub const CORE_2D: &str = graph::NAME;
pub use camera_2d::*; pub use camera_2d::*;
pub use main_pass_2d_node::*; pub use main_pass_2d_node::*;
@ -26,7 +27,7 @@ use bevy_ecs::prelude::*;
use bevy_render::{ use bevy_render::{
camera::Camera, camera::Camera,
extract_component::ExtractComponentPlugin, extract_component::ExtractComponentPlugin,
render_graph::{EmptyNode, RenderGraph}, render_graph::{EmptyNode, RenderGraphApp},
render_phase::{ render_phase::{
batch_phase_system, sort_phase_system, BatchedPhaseItem, CachedRenderPipelinePhaseItem, batch_phase_system, sort_phase_system, BatchedPhaseItem, CachedRenderPipelinePhaseItem,
DrawFunctionId, DrawFunctions, PhaseItem, RenderPhase, DrawFunctionId, DrawFunctions, PhaseItem, RenderPhase,
@ -64,25 +65,24 @@ impl Plugin for Core2dPlugin {
), ),
); );
let pass_node_2d = MainPass2dNode::new(&mut render_app.world); {
let tonemapping = TonemappingNode::new(&mut render_app.world); use graph::node::*;
let upscaling = UpscalingNode::new(&mut render_app.world); render_app
let mut graph = render_app.world.resource_mut::<RenderGraph>(); .add_render_sub_graph(CORE_2D)
.add_render_graph_node::<MainPass2dNode>(CORE_2D, MAIN_PASS)
let mut draw_2d_graph = RenderGraph::default(); .add_render_graph_node::<TonemappingNode>(CORE_2D, TONEMAPPING)
draw_2d_graph.add_node(graph::node::MAIN_PASS, pass_node_2d); .add_render_graph_node::<EmptyNode>(CORE_2D, END_MAIN_PASS_POST_PROCESSING)
draw_2d_graph.add_node(graph::node::TONEMAPPING, tonemapping); .add_render_graph_node::<UpscalingNode>(CORE_2D, UPSCALING)
draw_2d_graph.add_node(graph::node::END_MAIN_PASS_POST_PROCESSING, EmptyNode); .add_render_graph_edges(
draw_2d_graph.add_node(graph::node::UPSCALING, upscaling); CORE_2D,
&[
draw_2d_graph.add_node_edges(&[ MAIN_PASS,
graph::node::MAIN_PASS, TONEMAPPING,
graph::node::TONEMAPPING, END_MAIN_PASS_POST_PROCESSING,
graph::node::END_MAIN_PASS_POST_PROCESSING, UPSCALING,
graph::node::UPSCALING, ],
]); );
}
graph.add_sub_graph(graph::NAME, draw_2d_graph);
} }
} }

View File

@ -41,8 +41,8 @@ pub struct MainOpaquePass3dNode {
>, >,
} }
impl MainOpaquePass3dNode { impl FromWorld for MainOpaquePass3dNode {
pub fn new(world: &mut World) -> Self { fn from_world(world: &mut World) -> Self {
Self { Self {
query: world.query_filtered(), query: world.query_filtered(),
} }

View File

@ -24,8 +24,8 @@ pub struct MainTransparentPass3dNode {
>, >,
} }
impl MainTransparentPass3dNode { impl FromWorld for MainTransparentPass3dNode {
pub fn new(world: &mut World) -> Self { fn from_world(world: &mut World) -> Self {
Self { Self {
query: world.query_filtered(), query: world.query_filtered(),
} }

View File

@ -22,6 +22,7 @@ pub mod graph {
pub const END_MAIN_PASS_POST_PROCESSING: &str = "end_main_pass_post_processing"; pub const END_MAIN_PASS_POST_PROCESSING: &str = "end_main_pass_post_processing";
} }
} }
pub const CORE_3D: &str = graph::NAME;
use std::cmp::Reverse; use std::cmp::Reverse;
@ -35,7 +36,7 @@ use bevy_render::{
camera::{Camera, ExtractedCamera}, camera::{Camera, ExtractedCamera},
extract_component::ExtractComponentPlugin, extract_component::ExtractComponentPlugin,
prelude::Msaa, prelude::Msaa,
render_graph::{EmptyNode, RenderGraph}, render_graph::{EmptyNode, RenderGraphApp},
render_phase::{ render_phase::{
sort_phase_system, CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem, sort_phase_system, CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem,
RenderPhase, RenderPhase,
@ -89,35 +90,30 @@ impl Plugin for Core3dPlugin {
), ),
); );
let prepass_node = PrepassNode::new(&mut render_app.world); use graph::node::*;
let opaque_node_3d = MainOpaquePass3dNode::new(&mut render_app.world); render_app
let transparent_node_3d = MainTransparentPass3dNode::new(&mut render_app.world); .add_render_sub_graph(CORE_3D)
let tonemapping = TonemappingNode::new(&mut render_app.world); .add_render_graph_node::<PrepassNode>(CORE_3D, PREPASS)
let upscaling = UpscalingNode::new(&mut render_app.world); .add_render_graph_node::<EmptyNode>(CORE_3D, START_MAIN_PASS)
let mut graph = render_app.world.resource_mut::<RenderGraph>(); .add_render_graph_node::<MainOpaquePass3dNode>(CORE_3D, MAIN_OPAQUE_PASS)
.add_render_graph_node::<MainTransparentPass3dNode>(CORE_3D, MAIN_TRANSPARENT_PASS)
let mut draw_3d_graph = RenderGraph::default(); .add_render_graph_node::<EmptyNode>(CORE_3D, END_MAIN_PASS)
draw_3d_graph.add_node(graph::node::PREPASS, prepass_node); .add_render_graph_node::<TonemappingNode>(CORE_3D, TONEMAPPING)
draw_3d_graph.add_node(graph::node::START_MAIN_PASS, EmptyNode); .add_render_graph_node::<EmptyNode>(CORE_3D, END_MAIN_PASS_POST_PROCESSING)
draw_3d_graph.add_node(graph::node::MAIN_OPAQUE_PASS, opaque_node_3d); .add_render_graph_node::<UpscalingNode>(CORE_3D, UPSCALING)
draw_3d_graph.add_node(graph::node::MAIN_TRANSPARENT_PASS, transparent_node_3d); .add_render_graph_edges(
draw_3d_graph.add_node(graph::node::END_MAIN_PASS, EmptyNode); CORE_3D,
draw_3d_graph.add_node(graph::node::TONEMAPPING, tonemapping); &[
draw_3d_graph.add_node(graph::node::END_MAIN_PASS_POST_PROCESSING, EmptyNode); PREPASS,
draw_3d_graph.add_node(graph::node::UPSCALING, upscaling); START_MAIN_PASS,
MAIN_OPAQUE_PASS,
draw_3d_graph.add_node_edges(&[ MAIN_TRANSPARENT_PASS,
graph::node::PREPASS, END_MAIN_PASS,
graph::node::START_MAIN_PASS, TONEMAPPING,
graph::node::MAIN_OPAQUE_PASS, END_MAIN_PASS_POST_PROCESSING,
graph::node::MAIN_TRANSPARENT_PASS, UPSCALING,
graph::node::END_MAIN_PASS, ],
graph::node::TONEMAPPING, );
graph::node::END_MAIN_PASS_POST_PROCESSING,
graph::node::UPSCALING,
]);
graph.add_sub_graph(graph::NAME, draw_3d_graph);
} }
} }

View File

@ -1,4 +1,8 @@
use crate::{core_2d, core_3d, fullscreen_vertex_shader::fullscreen_shader_vertex_state}; use crate::{
core_2d::{self, CORE_2D},
core_3d::{self, CORE_3D},
fullscreen_vertex_shader::fullscreen_shader_vertex_state,
};
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, HandleUntyped}; use bevy_asset::{load_internal_asset, HandleUntyped};
use bevy_derive::Deref; use bevy_derive::Deref;
@ -91,18 +95,18 @@ impl Plugin for FxaaPlugin {
.init_resource::<FxaaPipeline>() .init_resource::<FxaaPipeline>()
.init_resource::<SpecializedRenderPipelines<FxaaPipeline>>() .init_resource::<SpecializedRenderPipelines<FxaaPipeline>>()
.add_systems(Render, prepare_fxaa_pipelines.in_set(RenderSet::Prepare)) .add_systems(Render, prepare_fxaa_pipelines.in_set(RenderSet::Prepare))
.add_render_graph_node::<FxaaNode>(core_3d::graph::NAME, core_3d::graph::node::FXAA) .add_render_graph_node::<FxaaNode>(CORE_3D, core_3d::graph::node::FXAA)
.add_render_graph_edges( .add_render_graph_edges(
core_3d::graph::NAME, CORE_3D,
&[ &[
core_3d::graph::node::TONEMAPPING, core_3d::graph::node::TONEMAPPING,
core_3d::graph::node::FXAA, core_3d::graph::node::FXAA,
core_3d::graph::node::END_MAIN_PASS_POST_PROCESSING, core_3d::graph::node::END_MAIN_PASS_POST_PROCESSING,
], ],
) )
.add_render_graph_node::<FxaaNode>(core_2d::graph::NAME, core_2d::graph::node::FXAA) .add_render_graph_node::<FxaaNode>(CORE_2D, core_2d::graph::node::FXAA)
.add_render_graph_edges( .add_render_graph_edges(
core_2d::graph::NAME, CORE_2D,
&[ &[
core_2d::graph::node::TONEMAPPING, core_2d::graph::node::TONEMAPPING,
core_2d::graph::node::FXAA, core_2d::graph::node::FXAA,

View File

@ -1,9 +1,13 @@
use crate::blit::{BlitPipeline, BlitPipelineKey}; use crate::{
blit::{BlitPipeline, BlitPipelineKey},
core_2d::{self, CORE_2D},
core_3d::{self, CORE_3D},
};
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_render::{ use bevy_render::{
camera::ExtractedCamera, camera::ExtractedCamera,
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext}, render_graph::{Node, NodeRunError, RenderGraphApp, RenderGraphContext},
renderer::RenderContext, renderer::RenderContext,
view::{Msaa, ViewTarget}, view::{Msaa, ViewTarget},
Render, RenderSet, Render, RenderSet,
@ -24,29 +28,17 @@ impl Plugin for MsaaWritebackPlugin {
Render, Render,
queue_msaa_writeback_pipelines.in_set(RenderSet::Queue), queue_msaa_writeback_pipelines.in_set(RenderSet::Queue),
); );
let msaa_writeback_2d = MsaaWritebackNode::new(&mut render_app.world); {
let msaa_writeback_3d = MsaaWritebackNode::new(&mut render_app.world); use core_2d::graph::node::*;
let mut graph = render_app.world.resource_mut::<RenderGraph>(); render_app
if let Some(core_2d) = graph.get_sub_graph_mut(crate::core_2d::graph::NAME) { .add_render_graph_node::<MsaaWritebackNode>(CORE_2D, MSAA_WRITEBACK)
core_2d.add_node( .add_render_graph_edge(CORE_2D, MSAA_WRITEBACK, MAIN_PASS);
crate::core_2d::graph::node::MSAA_WRITEBACK,
msaa_writeback_2d,
);
core_2d.add_node_edge(
crate::core_2d::graph::node::MSAA_WRITEBACK,
crate::core_2d::graph::node::MAIN_PASS,
);
} }
{
if let Some(core_3d) = graph.get_sub_graph_mut(crate::core_3d::graph::NAME) { use core_3d::graph::node::*;
core_3d.add_node( render_app
crate::core_3d::graph::node::MSAA_WRITEBACK, .add_render_graph_node::<MsaaWritebackNode>(CORE_3D, MSAA_WRITEBACK)
msaa_writeback_3d, .add_render_graph_edge(CORE_3D, MSAA_WRITEBACK, START_MAIN_PASS);
);
core_3d.add_node_edge(
crate::core_3d::graph::node::MSAA_WRITEBACK,
crate::core_3d::graph::node::START_MAIN_PASS,
);
} }
} }
} }
@ -55,8 +47,8 @@ pub struct MsaaWritebackNode {
cameras: QueryState<(&'static ViewTarget, &'static MsaaWritebackBlitPipeline)>, cameras: QueryState<(&'static ViewTarget, &'static MsaaWritebackBlitPipeline)>,
} }
impl MsaaWritebackNode { impl FromWorld for MsaaWritebackNode {
pub fn new(world: &mut World) -> Self { fn from_world(world: &mut World) -> Self {
Self { Self {
cameras: world.query(), cameras: world.query(),
} }

View File

@ -33,8 +33,8 @@ pub struct PrepassNode {
>, >,
} }
impl PrepassNode { impl FromWorld for PrepassNode {
pub fn new(world: &mut World) -> Self { fn from_world(world: &mut World) -> Self {
Self { Self {
main_view_query: QueryState::new(world), main_view_query: QueryState::new(world),
} }

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
core_3d, core_3d::{self, CORE_3D},
fullscreen_vertex_shader::fullscreen_shader_vertex_state, fullscreen_vertex_shader::fullscreen_shader_vertex_state,
prelude::Camera3d, prelude::Camera3d,
prepass::{DepthPrepass, MotionVectorPrepass, ViewPrepassTextures}, prepass::{DepthPrepass, MotionVectorPrepass, ViewPrepassTextures},
@ -73,9 +73,9 @@ impl Plugin for TemporalAntiAliasPlugin {
prepare_taa_pipelines.in_set(RenderSet::Prepare), prepare_taa_pipelines.in_set(RenderSet::Prepare),
), ),
) )
.add_render_graph_node::<TAANode>(core_3d::graph::NAME, draw_3d_graph::node::TAA) .add_render_graph_node::<TAANode>(CORE_3D, draw_3d_graph::node::TAA)
.add_render_graph_edges( .add_render_graph_edges(
core_3d::graph::NAME, CORE_3D,
&[ &[
core_3d::graph::node::END_MAIN_PASS, core_3d::graph::node::END_MAIN_PASS,
draw_3d_graph::node::TAA, draw_3d_graph::node::TAA,

View File

@ -33,8 +33,8 @@ pub struct TonemappingNode {
last_tonemapping: Mutex<Option<Tonemapping>>, last_tonemapping: Mutex<Option<Tonemapping>>,
} }
impl TonemappingNode { impl FromWorld for TonemappingNode {
pub fn new(world: &mut World) -> Self { fn from_world(world: &mut World) -> Self {
Self { Self {
query: QueryState::new(world), query: QueryState::new(world),
cached_bind_group: Mutex::new(None), cached_bind_group: Mutex::new(None),

View File

@ -26,8 +26,8 @@ pub struct UpscalingNode {
cached_texture_bind_group: Mutex<Option<(TextureViewId, BindGroup)>>, cached_texture_bind_group: Mutex<Option<(TextureViewId, BindGroup)>>,
} }
impl UpscalingNode { impl FromWorld for UpscalingNode {
pub fn new(world: &mut World) -> Self { fn from_world(world: &mut World) -> Self {
Self { Self {
query: QueryState::new(world), query: QueryState::new(world),
cached_texture_bind_group: Mutex::new(None), cached_texture_bind_group: Mutex::new(None),

View File

@ -1,10 +1,13 @@
use bevy_app::App; use bevy_app::App;
use bevy_ecs::world::FromWorld; use bevy_ecs::world::FromWorld;
use bevy_log::warn;
use super::{Node, RenderGraph}; use super::{Node, RenderGraph};
/// Adds common [`RenderGraph`] operations to [`App`]. /// Adds common [`RenderGraph`] operations to [`App`].
pub trait RenderGraphApp { pub trait RenderGraphApp {
// Add a sub graph to the [`RenderGraph`]
fn add_render_sub_graph(&mut self, sub_graph_name: &'static str) -> &mut Self;
/// Add a [`Node`] to the [`RenderGraph`]: /// Add a [`Node`] to the [`RenderGraph`]:
/// * Create the [`Node`] using the [`FromWorld`] implementation /// * Create the [`Node`] using the [`FromWorld`] implementation
/// * Add it to the graph /// * Add it to the graph
@ -38,9 +41,11 @@ impl RenderGraphApp for App {
let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect( let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect(
"RenderGraph not found. Make sure you are using add_render_graph_node on the RenderApp", "RenderGraph not found. Make sure you are using add_render_graph_node on the RenderApp",
); );
if let Some(graph) = render_graph.get_sub_graph_mut(sub_graph_name) {
let graph = render_graph.sub_graph_mut(sub_graph_name);
graph.add_node(node_name, node); graph.add_node(node_name, node);
} else {
warn!("Tried adding a render graph node to {sub_graph_name} but the sub graph doesn't exist");
}
self self
} }
@ -50,10 +55,13 @@ impl RenderGraphApp for App {
edges: &[&'static str], edges: &[&'static str],
) -> &mut Self { ) -> &mut Self {
let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect( let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect(
"RenderGraph not found. Make sure you are using add_render_graph_node on the RenderApp", "RenderGraph not found. Make sure you are using add_render_graph_edges on the RenderApp",
); );
let graph = render_graph.sub_graph_mut(sub_graph_name); if let Some(graph) = render_graph.get_sub_graph_mut(sub_graph_name) {
graph.add_node_edges(edges); graph.add_node_edges(edges);
} else {
warn!("Tried adding render graph edges to {sub_graph_name} but the sub graph doesn't exist");
}
self self
} }
@ -64,10 +72,21 @@ impl RenderGraphApp for App {
input_edge: &'static str, input_edge: &'static str,
) -> &mut Self { ) -> &mut Self {
let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect( let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect(
"RenderGraph not found. Make sure you are using add_render_graph_node on the RenderApp", "RenderGraph not found. Make sure you are using add_render_graph_edge on the RenderApp",
); );
let graph = render_graph.sub_graph_mut(sub_graph_name); if let Some(graph) = render_graph.get_sub_graph_mut(sub_graph_name) {
graph.add_node_edge(output_edge, input_edge); graph.add_node_edge(output_edge, input_edge);
} else {
warn!("Tried adding a render graph edge to {sub_graph_name} but the sub graph doesn't exist");
}
self
}
fn add_render_sub_graph(&mut self, sub_graph_name: &'static str) -> &mut Self {
let mut render_graph = self.world.get_resource_mut::<RenderGraph>().expect(
"RenderGraph not found. Make sure you are using add_render_sub_graph on the RenderApp",
);
render_graph.add_sub_graph(sub_graph_name, RenderGraph::default());
self self
} }
} }

View File

@ -293,6 +293,7 @@ impl From<NodeId> for NodeLabel {
/// A [`Node`] without any inputs, outputs and subgraphs, which does nothing when run. /// A [`Node`] without any inputs, outputs and subgraphs, which does nothing when run.
/// Used (as a label) to bundle multiple dependencies into one inside /// Used (as a label) to bundle multiple dependencies into one inside
/// the [`RenderGraph`](super::RenderGraph). /// the [`RenderGraph`](super::RenderGraph).
#[derive(Default)]
pub struct EmptyNode; pub struct EmptyNode;
impl Node for EmptyNode { impl Node for EmptyNode {