Make render graph slots optional for most cases (#8109)

# Objective

- Currently, the render graph slots are only used to pass the
view_entity around. This introduces significant boilerplate for very
little value. Instead of using slots for this, make the view_entity part
of the `RenderGraphContext`. This also means we won't need to have
`IN_VIEW` on every node and and we'll be able to use the default impl of
`Node::input()`.

## Solution

- Add `view_entity: Option<Entity>` to the `RenderGraphContext`
- Update all nodes to use this instead of entity slot input

---

## Changelog

- Add optional `view_entity` to `RenderGraphContext`

## Migration Guide

You can now get the view_entity directly from the `RenderGraphContext`. 

When implementing the Node:

```rust
// 0.10
struct FooNode;
impl FooNode {
    const IN_VIEW: &'static str = "view";
}
impl Node for FooNode {
    fn input(&self) -> Vec<SlotInfo> {
        vec![SlotInfo::new(Self::IN_VIEW, SlotType::Entity)]
    }
    fn run(
        &self,
        graph: &mut RenderGraphContext,
        // ... 
    ) -> Result<(), NodeRunError> {
        let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
        // ...
        Ok(())
    }
}

// 0.11
struct FooNode;
impl Node for FooNode {
    fn run(
        &self,
        graph: &mut RenderGraphContext,
        // ... 
    ) -> Result<(), NodeRunError> {
        let view_entity = graph.view_entity();
        // ...
        Ok(())
    }
}
```

When adding the node to the graph, you don't need to specify a slot_edge
for the view_entity.

```rust
// 0.10
let mut graph = RenderGraph::default();
graph.add_node(FooNode::NAME, node);
let input_node_id = draw_2d_graph.set_input(vec![SlotInfo::new(
    graph::input::VIEW_ENTITY,
    SlotType::Entity,
)]);
graph.add_slot_edge(
    input_node_id,
    graph::input::VIEW_ENTITY,
    FooNode::NAME,
    FooNode::IN_VIEW,
);
// add_node_edge ...

// 0.11
let mut graph = RenderGraph::default();
graph.add_node(FooNode::NAME, node);
// add_node_edge ...
```

## Notes

This PR paired with #8007 will help reduce a lot of annoying boilerplate
with the render nodes. Depending on which one gets merged first. It will
require a bit of clean up work to make both compatible.

I tagged this as a breaking change, because using the old system to get
the view_entity will break things because it's not a node input slot
anymore.

## Notes for reviewers

A lot of the diffs are just removing the slots in every nodes and graph
creation. The important part is mostly in the
graph_runner/CameraDriverNode.
This commit is contained in:
IceSentry 2023-03-21 16:11:13 -04:00 committed by GitHub
parent 353f2e0b37
commit 2c21d423fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 63 additions and 239 deletions

View File

@ -16,7 +16,7 @@ use bevy_render::{
ComponentUniforms, DynamicUniformIndex, ExtractComponentPlugin, UniformComponentPlugin, ComponentUniforms, DynamicUniformIndex, ExtractComponentPlugin, UniformComponentPlugin,
}, },
prelude::Color, prelude::Color,
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext},
render_resource::*, render_resource::*,
renderer::{RenderContext, RenderDevice}, renderer::{RenderContext, RenderDevice},
texture::{CachedTexture, TextureCache}, texture::{CachedTexture, TextureCache},
@ -83,12 +83,6 @@ impl Plugin for BloomPlugin {
.get_sub_graph_mut(crate::core_3d::graph::NAME) .get_sub_graph_mut(crate::core_3d::graph::NAME)
.unwrap(); .unwrap();
draw_3d_graph.add_node(core_3d::graph::node::BLOOM, bloom_node); draw_3d_graph.add_node(core_3d::graph::node::BLOOM, bloom_node);
draw_3d_graph.add_slot_edge(
draw_3d_graph.input_node().id,
crate::core_3d::graph::input::VIEW_ENTITY,
core_3d::graph::node::BLOOM,
BloomNode::IN_VIEW,
);
// MAIN_PASS -> BLOOM -> TONEMAPPING // MAIN_PASS -> BLOOM -> TONEMAPPING
draw_3d_graph.add_node_edge( draw_3d_graph.add_node_edge(
crate::core_3d::graph::node::MAIN_PASS, crate::core_3d::graph::node::MAIN_PASS,
@ -108,12 +102,6 @@ impl Plugin for BloomPlugin {
.get_sub_graph_mut(crate::core_2d::graph::NAME) .get_sub_graph_mut(crate::core_2d::graph::NAME)
.unwrap(); .unwrap();
draw_2d_graph.add_node(core_2d::graph::node::BLOOM, bloom_node); draw_2d_graph.add_node(core_2d::graph::node::BLOOM, bloom_node);
draw_2d_graph.add_slot_edge(
draw_2d_graph.input_node().id,
crate::core_2d::graph::input::VIEW_ENTITY,
core_2d::graph::node::BLOOM,
BloomNode::IN_VIEW,
);
// MAIN_PASS -> BLOOM -> TONEMAPPING // MAIN_PASS -> BLOOM -> TONEMAPPING
draw_2d_graph.add_node_edge( draw_2d_graph.add_node_edge(
crate::core_2d::graph::node::MAIN_PASS, crate::core_2d::graph::node::MAIN_PASS,
@ -141,8 +129,6 @@ pub struct BloomNode {
} }
impl BloomNode { impl BloomNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
view_query: QueryState::new(world), view_query: QueryState::new(world),
@ -151,10 +137,6 @@ impl BloomNode {
} }
impl Node for BloomNode { impl Node for BloomNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(Self::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.view_query.update_archetypes(world); self.view_query.update_archetypes(world);
} }
@ -174,7 +156,7 @@ impl Node for BloomNode {
let downsampling_pipeline_res = world.resource::<BloomDownsamplingPipeline>(); let downsampling_pipeline_res = world.resource::<BloomDownsamplingPipeline>();
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();
let uniforms = world.resource::<ComponentUniforms<BloomUniforms>>(); let uniforms = world.resource::<ComponentUniforms<BloomUniforms>>();
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
let Ok(( let Ok((
camera, camera,
view_target, view_target,

View File

@ -5,7 +5,7 @@ use crate::{
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_render::{ use bevy_render::{
camera::ExtractedCamera, camera::ExtractedCamera,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::RenderPhase, render_phase::RenderPhase,
render_resource::{LoadOp, Operations, RenderPassDescriptor}, render_resource::{LoadOp, Operations, RenderPassDescriptor},
renderer::RenderContext, renderer::RenderContext,
@ -27,8 +27,6 @@ pub struct MainPass2dNode {
} }
impl MainPass2dNode { impl MainPass2dNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
query: world.query_filtered(), query: world.query_filtered(),
@ -37,10 +35,6 @@ impl MainPass2dNode {
} }
impl Node for MainPass2dNode { impl Node for MainPass2dNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(MainPass2dNode::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.query.update_archetypes(world); self.query.update_archetypes(world);
} }
@ -51,7 +45,7 @@ impl Node for MainPass2dNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
let (camera, transparent_phase, target, camera_2d) = let (camera, transparent_phase, target, camera_2d) =
if let Ok(result) = self.query.get_manual(world, view_entity) { if let Ok(result) = self.query.get_manual(world, view_entity) {
result result

View File

@ -25,7 +25,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, SlotInfo, SlotType}, render_graph::{EmptyNode, RenderGraph},
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,
@ -73,28 +73,6 @@ impl Plugin for Core2dPlugin {
draw_2d_graph.add_node(graph::node::TONEMAPPING, tonemapping); draw_2d_graph.add_node(graph::node::TONEMAPPING, tonemapping);
draw_2d_graph.add_node(graph::node::END_MAIN_PASS_POST_PROCESSING, EmptyNode); draw_2d_graph.add_node(graph::node::END_MAIN_PASS_POST_PROCESSING, EmptyNode);
draw_2d_graph.add_node(graph::node::UPSCALING, upscaling); draw_2d_graph.add_node(graph::node::UPSCALING, upscaling);
let input_node_id = draw_2d_graph.set_input(vec![SlotInfo::new(
graph::input::VIEW_ENTITY,
SlotType::Entity,
)]);
draw_2d_graph.add_slot_edge(
input_node_id,
graph::input::VIEW_ENTITY,
graph::node::MAIN_PASS,
MainPass2dNode::IN_VIEW,
);
draw_2d_graph.add_slot_edge(
input_node_id,
graph::input::VIEW_ENTITY,
graph::node::TONEMAPPING,
TonemappingNode::IN_VIEW,
);
draw_2d_graph.add_slot_edge(
input_node_id,
graph::input::VIEW_ENTITY,
graph::node::UPSCALING,
UpscalingNode::IN_VIEW,
);
draw_2d_graph.add_node_edge(graph::node::MAIN_PASS, graph::node::TONEMAPPING); draw_2d_graph.add_node_edge(graph::node::MAIN_PASS, graph::node::TONEMAPPING);
draw_2d_graph.add_node_edge( draw_2d_graph.add_node_edge(
graph::node::TONEMAPPING, graph::node::TONEMAPPING,

View File

@ -6,7 +6,7 @@ use crate::{
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_render::{ use bevy_render::{
camera::ExtractedCamera, camera::ExtractedCamera,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::RenderPhase, render_phase::RenderPhase,
render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor}, render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor},
renderer::RenderContext, renderer::RenderContext,
@ -35,8 +35,6 @@ pub struct MainPass3dNode {
} }
impl MainPass3dNode { impl MainPass3dNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
query: world.query_filtered(), query: world.query_filtered(),
@ -45,10 +43,6 @@ impl MainPass3dNode {
} }
impl Node for MainPass3dNode { impl Node for MainPass3dNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(MainPass3dNode::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.query.update_archetypes(world); self.query.update_archetypes(world);
} }
@ -59,7 +53,7 @@ impl Node for MainPass3dNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
let Ok(( let Ok((
camera, camera,
opaque_phase, opaque_phase,

View File

@ -29,7 +29,7 @@ use bevy_render::{
camera::{Camera, ExtractedCamera}, camera::{Camera, ExtractedCamera},
extract_component::ExtractComponentPlugin, extract_component::ExtractComponentPlugin,
prelude::Msaa, prelude::Msaa,
render_graph::{EmptyNode, RenderGraph, SlotInfo, SlotType}, render_graph::{EmptyNode, RenderGraph},
render_phase::{ render_phase::{
sort_phase_system, CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem, sort_phase_system, CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem,
RenderPhase, RenderPhase,
@ -94,34 +94,6 @@ impl Plugin for Core3dPlugin {
draw_3d_graph.add_node(graph::node::END_MAIN_PASS_POST_PROCESSING, EmptyNode); draw_3d_graph.add_node(graph::node::END_MAIN_PASS_POST_PROCESSING, EmptyNode);
draw_3d_graph.add_node(graph::node::UPSCALING, upscaling); draw_3d_graph.add_node(graph::node::UPSCALING, upscaling);
let input_node_id = draw_3d_graph.set_input(vec![SlotInfo::new(
graph::input::VIEW_ENTITY,
SlotType::Entity,
)]);
draw_3d_graph.add_slot_edge(
input_node_id,
graph::input::VIEW_ENTITY,
graph::node::PREPASS,
PrepassNode::IN_VIEW,
);
draw_3d_graph.add_slot_edge(
input_node_id,
graph::input::VIEW_ENTITY,
graph::node::MAIN_PASS,
MainPass3dNode::IN_VIEW,
);
draw_3d_graph.add_slot_edge(
input_node_id,
graph::input::VIEW_ENTITY,
graph::node::TONEMAPPING,
TonemappingNode::IN_VIEW,
);
draw_3d_graph.add_slot_edge(
input_node_id,
graph::input::VIEW_ENTITY,
graph::node::UPSCALING,
UpscalingNode::IN_VIEW,
);
draw_3d_graph.add_node_edge(graph::node::PREPASS, graph::node::MAIN_PASS); draw_3d_graph.add_node_edge(graph::node::PREPASS, graph::node::MAIN_PASS);
draw_3d_graph.add_node_edge(graph::node::MAIN_PASS, graph::node::TONEMAPPING); draw_3d_graph.add_node_edge(graph::node::MAIN_PASS, graph::node::TONEMAPPING);
draw_3d_graph.add_node_edge( draw_3d_graph.add_node_edge(

View File

@ -99,13 +99,6 @@ impl Plugin for FxaaPlugin {
graph.add_node(core_3d::graph::node::FXAA, fxaa_node); graph.add_node(core_3d::graph::node::FXAA, fxaa_node);
graph.add_slot_edge(
graph.input_node().id,
core_3d::graph::input::VIEW_ENTITY,
core_3d::graph::node::FXAA,
FxaaNode::IN_VIEW,
);
graph.add_node_edge( graph.add_node_edge(
core_3d::graph::node::TONEMAPPING, core_3d::graph::node::TONEMAPPING,
core_3d::graph::node::FXAA, core_3d::graph::node::FXAA,
@ -122,13 +115,6 @@ impl Plugin for FxaaPlugin {
graph.add_node(core_2d::graph::node::FXAA, fxaa_node); graph.add_node(core_2d::graph::node::FXAA, fxaa_node);
graph.add_slot_edge(
graph.input_node().id,
core_2d::graph::input::VIEW_ENTITY,
core_2d::graph::node::FXAA,
FxaaNode::IN_VIEW,
);
graph.add_node_edge( graph.add_node_edge(
core_2d::graph::node::TONEMAPPING, core_2d::graph::node::TONEMAPPING,
core_2d::graph::node::FXAA, core_2d::graph::node::FXAA,

View File

@ -4,7 +4,7 @@ use crate::fxaa::{CameraFxaaPipeline, Fxaa, FxaaPipeline};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_ecs::query::QueryState; use bevy_ecs::query::QueryState;
use bevy_render::{ use bevy_render::{
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraphContext},
render_resource::{ render_resource::{
BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, FilterMode, Operations, BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, FilterMode, Operations,
PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor,
@ -28,8 +28,6 @@ pub struct FxaaNode {
} }
impl FxaaNode { impl FxaaNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
query: QueryState::new(world), query: QueryState::new(world),
@ -39,10 +37,6 @@ impl FxaaNode {
} }
impl Node for FxaaNode { impl Node for FxaaNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(FxaaNode::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.query.update_archetypes(world); self.query.update_archetypes(world);
} }
@ -53,7 +47,7 @@ impl Node for FxaaNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();
let fxaa_pipeline = world.resource::<FxaaPipeline>(); let fxaa_pipeline = world.resource::<FxaaPipeline>();

View File

@ -3,7 +3,7 @@ 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, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext},
renderer::RenderContext, renderer::RenderContext,
view::{Msaa, ViewTarget}, view::{Msaa, ViewTarget},
Render, RenderSet, Render, RenderSet,
@ -28,7 +28,6 @@ impl Plugin for MsaaWritebackPlugin {
let msaa_writeback_3d = MsaaWritebackNode::new(&mut render_app.world); let msaa_writeback_3d = MsaaWritebackNode::new(&mut render_app.world);
let mut graph = render_app.world.resource_mut::<RenderGraph>(); let mut graph = render_app.world.resource_mut::<RenderGraph>();
if let Some(core_2d) = graph.get_sub_graph_mut(crate::core_2d::graph::NAME) { if let Some(core_2d) = graph.get_sub_graph_mut(crate::core_2d::graph::NAME) {
let input_node = core_2d.input_node().id;
core_2d.add_node( core_2d.add_node(
crate::core_2d::graph::node::MSAA_WRITEBACK, crate::core_2d::graph::node::MSAA_WRITEBACK,
msaa_writeback_2d, msaa_writeback_2d,
@ -37,16 +36,9 @@ impl Plugin for MsaaWritebackPlugin {
crate::core_2d::graph::node::MSAA_WRITEBACK, crate::core_2d::graph::node::MSAA_WRITEBACK,
crate::core_2d::graph::node::MAIN_PASS, crate::core_2d::graph::node::MAIN_PASS,
); );
core_2d.add_slot_edge(
input_node,
crate::core_2d::graph::input::VIEW_ENTITY,
crate::core_2d::graph::node::MSAA_WRITEBACK,
MsaaWritebackNode::IN_VIEW,
);
} }
if let Some(core_3d) = graph.get_sub_graph_mut(crate::core_3d::graph::NAME) { if let Some(core_3d) = graph.get_sub_graph_mut(crate::core_3d::graph::NAME) {
let input_node = core_3d.input_node().id;
core_3d.add_node( core_3d.add_node(
crate::core_3d::graph::node::MSAA_WRITEBACK, crate::core_3d::graph::node::MSAA_WRITEBACK,
msaa_writeback_3d, msaa_writeback_3d,
@ -55,12 +47,6 @@ impl Plugin for MsaaWritebackPlugin {
crate::core_3d::graph::node::MSAA_WRITEBACK, crate::core_3d::graph::node::MSAA_WRITEBACK,
crate::core_3d::graph::node::MAIN_PASS, crate::core_3d::graph::node::MAIN_PASS,
); );
core_3d.add_slot_edge(
input_node,
crate::core_3d::graph::input::VIEW_ENTITY,
crate::core_3d::graph::node::MSAA_WRITEBACK,
MsaaWritebackNode::IN_VIEW,
);
} }
} }
} }
@ -70,8 +56,6 @@ pub struct MsaaWritebackNode {
} }
impl MsaaWritebackNode { impl MsaaWritebackNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
cameras: world.query(), cameras: world.query(),
@ -80,9 +64,6 @@ impl MsaaWritebackNode {
} }
impl Node for MsaaWritebackNode { impl Node for MsaaWritebackNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(Self::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.cameras.update_archetypes(world); self.cameras.update_archetypes(world);
} }
@ -92,7 +73,7 @@ impl Node for MsaaWritebackNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
if let Ok((target, blit_pipeline_id)) = self.cameras.get_manual(world, view_entity) { if let Ok((target, blit_pipeline_id)) = self.cameras.get_manual(world, view_entity) {
let blit_pipeline = world.resource::<BlitPipeline>(); let blit_pipeline = world.resource::<BlitPipeline>();
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();

View File

@ -3,7 +3,7 @@ use bevy_ecs::query::QueryState;
use bevy_render::{ use bevy_render::{
camera::ExtractedCamera, camera::ExtractedCamera,
prelude::Color, prelude::Color,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::RenderPhase, render_phase::RenderPhase,
render_resource::{ render_resource::{
LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment, LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment,
@ -34,8 +34,6 @@ pub struct PrepassNode {
} }
impl PrepassNode { impl PrepassNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
main_view_query: QueryState::new(world), main_view_query: QueryState::new(world),
@ -44,10 +42,6 @@ impl PrepassNode {
} }
impl Node for PrepassNode { impl Node for PrepassNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(Self::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.main_view_query.update_archetypes(world); self.main_view_query.update_archetypes(world);
} }
@ -58,7 +52,7 @@ impl Node for PrepassNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
let Ok(( let Ok((
camera, camera,
opaque_prepass_phase, opaque_prepass_phase,

View File

@ -6,7 +6,7 @@ use bevy_ecs::prelude::*;
use bevy_ecs::query::QueryState; use bevy_ecs::query::QueryState;
use bevy_render::{ use bevy_render::{
render_asset::RenderAssets, render_asset::RenderAssets,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraphContext},
render_resource::{ render_resource::{
BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferId, LoadOp, BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferId, LoadOp,
Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor,
@ -34,8 +34,6 @@ pub struct TonemappingNode {
} }
impl TonemappingNode { impl TonemappingNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
query: QueryState::new(world), query: QueryState::new(world),
@ -46,10 +44,6 @@ impl TonemappingNode {
} }
impl Node for TonemappingNode { impl Node for TonemappingNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(TonemappingNode::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.query.update_archetypes(world); self.query.update_archetypes(world);
} }
@ -60,7 +54,7 @@ impl Node for TonemappingNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
let pipeline_cache = world.resource::<PipelineCache>(); let pipeline_cache = world.resource::<PipelineCache>();
let tonemapping_pipeline = world.resource::<TonemappingPipeline>(); let tonemapping_pipeline = world.resource::<TonemappingPipeline>();
let gpu_images = world.get_resource::<RenderAssets<Image>>().unwrap(); let gpu_images = world.get_resource::<RenderAssets<Image>>().unwrap();

View File

@ -3,7 +3,7 @@ use bevy_ecs::prelude::*;
use bevy_ecs::query::QueryState; use bevy_ecs::query::QueryState;
use bevy_render::{ use bevy_render::{
camera::{CameraOutputMode, ExtractedCamera}, camera::{CameraOutputMode, ExtractedCamera},
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraphContext},
render_resource::{ render_resource::{
BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, LoadOp, Operations, BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, LoadOp, Operations,
PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor,
@ -27,8 +27,6 @@ pub struct UpscalingNode {
} }
impl UpscalingNode { impl UpscalingNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
query: QueryState::new(world), query: QueryState::new(world),
@ -38,10 +36,6 @@ impl UpscalingNode {
} }
impl Node for UpscalingNode { impl Node for UpscalingNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(UpscalingNode::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.query.update_archetypes(world); self.query.update_archetypes(world);
} }
@ -52,7 +46,7 @@ impl Node for UpscalingNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
let pipeline_cache = world.get_resource::<PipelineCache>().unwrap(); let pipeline_cache = world.get_resource::<PipelineCache>().unwrap();
let blit_pipeline = world.get_resource::<BlitPipeline>().unwrap(); let blit_pipeline = world.get_resource::<BlitPipeline>().unwrap();

View File

@ -294,11 +294,5 @@ impl Plugin for PbrPlugin {
draw_3d_graph::node::SHADOW_PASS, draw_3d_graph::node::SHADOW_PASS,
bevy_core_pipeline::core_3d::graph::node::MAIN_PASS, bevy_core_pipeline::core_3d::graph::node::MAIN_PASS,
); );
draw_3d_graph.add_slot_edge(
draw_3d_graph.input_node().id,
bevy_core_pipeline::core_3d::graph::input::VIEW_ENTITY,
draw_3d_graph::node::SHADOW_PASS,
ShadowPassNode::IN_VIEW,
);
} }
} }

View File

@ -15,7 +15,7 @@ use bevy_render::{
color::Color, color::Color,
mesh::Mesh, mesh::Mesh,
render_asset::RenderAssets, render_asset::RenderAssets,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::{ render_phase::{
CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem, RenderPhase, CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem, RenderPhase,
}, },
@ -1697,8 +1697,6 @@ pub struct ShadowPassNode {
} }
impl ShadowPassNode { impl ShadowPassNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
main_view_query: QueryState::new(world), main_view_query: QueryState::new(world),
@ -1708,10 +1706,6 @@ impl ShadowPassNode {
} }
impl Node for ShadowPassNode { impl Node for ShadowPassNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(ShadowPassNode::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.main_view_query.update_archetypes(world); self.main_view_query.update_archetypes(world);
self.view_light_query.update_archetypes(world); self.view_light_query.update_archetypes(world);
@ -1723,7 +1717,7 @@ impl Node for ShadowPassNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; let view_entity = graph.view_entity();
if let Ok(view_lights) = self.main_view_query.get_manual(world, view_entity) { if let Ok(view_lights) = self.main_view_query.get_manual(world, view_entity) {
for view_light_entity in view_lights.lights.iter().copied() { for view_light_entity in view_lights.lights.iter().copied() {
let (view_light, shadow_phase) = self let (view_light, shadow_phase) = self

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
camera::{ExtractedCamera, NormalizedRenderTarget, SortedCameras}, camera::{ExtractedCamera, NormalizedRenderTarget, SortedCameras},
render_graph::{Node, NodeRunError, RenderGraphContext, SlotValue}, render_graph::{Node, NodeRunError, RenderGraphContext},
renderer::RenderContext, renderer::RenderContext,
view::ExtractedWindows, view::ExtractedWindows,
}; };
@ -39,7 +39,8 @@ impl Node for CameraDriverNode {
} }
graph.run_sub_graph( graph.run_sub_graph(
camera.render_graph.clone(), camera.render_graph.clone(),
vec![SlotValue::Entity(sorted_camera.entity)], vec![],
Some(sorted_camera.entity),
)?; )?;
} }
} }

View File

@ -11,6 +11,7 @@ use thiserror::Error;
pub struct RunSubGraph { pub struct RunSubGraph {
pub name: Cow<'static, str>, pub name: Cow<'static, str>,
pub inputs: Vec<SlotValue>, pub inputs: Vec<SlotValue>,
pub view_entity: Option<Entity>,
} }
/// The context with all graph information required to run a [`Node`](super::Node). /// The context with all graph information required to run a [`Node`](super::Node).
@ -27,6 +28,11 @@ pub struct RenderGraphContext<'a> {
inputs: &'a [SlotValue], inputs: &'a [SlotValue],
outputs: &'a mut [Option<SlotValue>], outputs: &'a mut [Option<SlotValue>],
run_sub_graphs: Vec<RunSubGraph>, run_sub_graphs: Vec<RunSubGraph>,
/// The view_entity associated with the render graph being executed
/// This is optional because you aren't required to have a view_entity for a node.
/// For example, compute shader nodes don't have one.
/// It should always be set when the RenderGraph is running on a View.
view_entity: Option<Entity>,
} }
impl<'a> RenderGraphContext<'a> { impl<'a> RenderGraphContext<'a> {
@ -43,6 +49,7 @@ impl<'a> RenderGraphContext<'a> {
inputs, inputs,
outputs, outputs,
run_sub_graphs: Vec::new(), run_sub_graphs: Vec::new(),
view_entity: None,
} }
} }
@ -158,11 +165,24 @@ impl<'a> RenderGraphContext<'a> {
Ok(()) Ok(())
} }
pub fn view_entity(&self) -> Entity {
self.view_entity.unwrap()
}
pub fn get_view_entity(&self) -> Option<Entity> {
self.view_entity
}
pub fn set_view_entity(&mut self, view_entity: Entity) {
self.view_entity = Some(view_entity);
}
/// Queues up a sub graph for execution after the node has finished running. /// Queues up a sub graph for execution after the node has finished running.
pub fn run_sub_graph( pub fn run_sub_graph(
&mut self, &mut self,
name: impl Into<Cow<'static, str>>, name: impl Into<Cow<'static, str>>,
inputs: Vec<SlotValue>, inputs: Vec<SlotValue>,
view_entity: Option<Entity>,
) -> Result<(), RunSubGraphError> { ) -> Result<(), RunSubGraphError> {
let name = name.into(); let name = name.into();
let sub_graph = self let sub_graph = self
@ -193,7 +213,11 @@ impl<'a> RenderGraphContext<'a> {
return Err(RunSubGraphError::SubGraphHasNoInputs(name)); return Err(RunSubGraphError::SubGraphHasNoInputs(name));
} }
self.run_sub_graphs.push(RunSubGraph { name, inputs }); self.run_sub_graphs.push(RunSubGraph {
name,
inputs,
view_entity,
});
Ok(()) Ok(())
} }

View File

@ -2,7 +2,7 @@ use crate::{
define_atomic_id, define_atomic_id,
render_graph::{ render_graph::{
Edge, InputSlotError, OutputSlotError, RenderGraphContext, RenderGraphError, Edge, InputSlotError, OutputSlotError, RenderGraphContext, RenderGraphError,
RunSubGraphError, SlotInfo, SlotInfos, SlotType, SlotValue, RunSubGraphError, SlotInfo, SlotInfos,
}, },
renderer::RenderContext, renderer::RenderContext,
}; };
@ -306,14 +306,13 @@ impl Node for EmptyNode {
} }
} }
/// A [`RenderGraph`](super::RenderGraph) [`Node`] that takes a view entity as input and runs the configured graph name once. /// A [`RenderGraph`](super::RenderGraph) [`Node`] that runs the configured graph name once.
/// This makes it easier to insert sub-graph runs into a graph. /// This makes it easier to insert sub-graph runs into a graph.
pub struct RunGraphOnViewNode { pub struct RunGraphOnViewNode {
graph_name: Cow<'static, str>, graph_name: Cow<'static, str>,
} }
impl RunGraphOnViewNode { impl RunGraphOnViewNode {
pub const IN_VIEW: &'static str = "view";
pub fn new<T: Into<Cow<'static, str>>>(graph_name: T) -> Self { pub fn new<T: Into<Cow<'static, str>>>(graph_name: T) -> Self {
Self { Self {
graph_name: graph_name.into(), graph_name: graph_name.into(),
@ -322,20 +321,13 @@ impl RunGraphOnViewNode {
} }
impl Node for RunGraphOnViewNode { impl Node for RunGraphOnViewNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(Self::IN_VIEW, SlotType::Entity)]
}
fn run( fn run(
&self, &self,
graph: &mut RenderGraphContext, graph: &mut RenderGraphContext,
_render_context: &mut RenderContext, _render_context: &mut RenderContext,
_world: &World, _world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let view_entity = graph.get_input_entity(Self::IN_VIEW)?; graph.run_sub_graph(self.graph_name.clone(), vec![], Some(graph.view_entity()))?;
graph.run_sub_graph(
self.graph_name.clone(),
vec![SlotValue::Entity(view_entity)],
)?;
Ok(()) Ok(())
} }
} }

View File

@ -1,4 +1,4 @@
use bevy_ecs::world::World; use bevy_ecs::{prelude::Entity, world::World};
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
use bevy_utils::tracing::info_span; use bevy_utils::tracing::info_span;
use bevy_utils::HashMap; use bevy_utils::HashMap;
@ -59,7 +59,7 @@ impl RenderGraphRunner {
world: &World, world: &World,
) -> Result<(), RenderGraphRunnerError> { ) -> Result<(), RenderGraphRunnerError> {
let mut render_context = RenderContext::new(render_device); let mut render_context = RenderContext::new(render_device);
Self::run_graph(graph, None, &mut render_context, world, &[])?; Self::run_graph(graph, None, &mut render_context, world, &[], None)?;
{ {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let _span = info_span!("submit_graph_commands").entered(); let _span = info_span!("submit_graph_commands").entered();
@ -74,6 +74,7 @@ impl RenderGraphRunner {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
inputs: &[SlotValue], inputs: &[SlotValue],
view_entity: Option<Entity>,
) -> Result<(), RenderGraphRunnerError> { ) -> Result<(), RenderGraphRunnerError> {
let mut node_outputs: HashMap<NodeId, SmallVec<[SlotValue; 4]>> = HashMap::default(); let mut node_outputs: HashMap<NodeId, SmallVec<[SlotValue; 4]>> = HashMap::default();
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
@ -175,6 +176,10 @@ impl RenderGraphRunner {
smallvec![None; node_state.output_slots.len()]; smallvec![None; node_state.output_slots.len()];
{ {
let mut context = RenderGraphContext::new(graph, node_state, &inputs, &mut outputs); let mut context = RenderGraphContext::new(graph, node_state, &inputs, &mut outputs);
if let Some(view_entity) = view_entity {
context.set_view_entity(view_entity);
}
{ {
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
let _span = info_span!("node", name = node_state.type_name).entered(); let _span = info_span!("node", name = node_state.type_name).entered();
@ -192,6 +197,7 @@ impl RenderGraphRunner {
render_context, render_context,
world, world,
&run_sub_graph.inputs, &run_sub_graph.inputs,
run_sub_graph.view_entity,
)?; )?;
} }
} }

View File

@ -19,7 +19,7 @@ use bevy_render::{
camera::Camera, camera::Camera,
color::Color, color::Color,
render_asset::RenderAssets, render_asset::RenderAssets,
render_graph::{RenderGraph, RunGraphOnViewNode, SlotInfo, SlotType}, render_graph::{RenderGraph, RunGraphOnViewNode},
render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions, RenderPhase}, render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions, RenderPhase},
render_resource::*, render_resource::*,
renderer::{RenderDevice, RenderQueue}, renderer::{RenderDevice, RenderQueue},
@ -44,9 +44,6 @@ pub mod node {
pub mod draw_ui_graph { pub mod draw_ui_graph {
pub const NAME: &str = "draw_ui"; pub const NAME: &str = "draw_ui";
pub mod input {
pub const VIEW_ENTITY: &str = "view_entity";
}
pub mod node { pub mod node {
pub const UI_PASS: &str = "ui_pass"; pub const UI_PASS: &str = "ui_pass";
} }
@ -110,12 +107,6 @@ pub fn build_ui_render(app: &mut App) {
bevy_core_pipeline::core_2d::graph::node::MAIN_PASS, bevy_core_pipeline::core_2d::graph::node::MAIN_PASS,
draw_ui_graph::node::UI_PASS, draw_ui_graph::node::UI_PASS,
); );
graph_2d.add_slot_edge(
graph_2d.input_node().id,
bevy_core_pipeline::core_2d::graph::input::VIEW_ENTITY,
draw_ui_graph::node::UI_PASS,
RunGraphOnViewNode::IN_VIEW,
);
graph_2d.add_node_edge( graph_2d.add_node_edge(
bevy_core_pipeline::core_2d::graph::node::END_MAIN_PASS_POST_PROCESSING, bevy_core_pipeline::core_2d::graph::node::END_MAIN_PASS_POST_PROCESSING,
draw_ui_graph::node::UI_PASS, draw_ui_graph::node::UI_PASS,
@ -144,12 +135,6 @@ pub fn build_ui_render(app: &mut App) {
draw_ui_graph::node::UI_PASS, draw_ui_graph::node::UI_PASS,
bevy_core_pipeline::core_3d::graph::node::UPSCALING, bevy_core_pipeline::core_3d::graph::node::UPSCALING,
); );
graph_3d.add_slot_edge(
graph_3d.input_node().id,
bevy_core_pipeline::core_3d::graph::input::VIEW_ENTITY,
draw_ui_graph::node::UI_PASS,
RunGraphOnViewNode::IN_VIEW,
);
} }
} }
@ -157,16 +142,6 @@ fn get_ui_graph(render_app: &mut App) -> RenderGraph {
let ui_pass_node = UiPassNode::new(&mut render_app.world); let ui_pass_node = UiPassNode::new(&mut render_app.world);
let mut ui_graph = RenderGraph::default(); let mut ui_graph = RenderGraph::default();
ui_graph.add_node(draw_ui_graph::node::UI_PASS, ui_pass_node); ui_graph.add_node(draw_ui_graph::node::UI_PASS, ui_pass_node);
let input_node_id = ui_graph.set_input(vec![SlotInfo::new(
draw_ui_graph::input::VIEW_ENTITY,
SlotType::Entity,
)]);
ui_graph.add_slot_edge(
input_node_id,
draw_ui_graph::input::VIEW_ENTITY,
draw_ui_graph::node::UI_PASS,
UiPassNode::IN_VIEW,
);
ui_graph ui_graph
} }

View File

@ -26,8 +26,6 @@ pub struct UiPassNode {
} }
impl UiPassNode { impl UiPassNode {
pub const IN_VIEW: &'static str = "view";
pub fn new(world: &mut World) -> Self { pub fn new(world: &mut World) -> Self {
Self { Self {
ui_view_query: world.query_filtered(), ui_view_query: world.query_filtered(),
@ -37,10 +35,6 @@ impl UiPassNode {
} }
impl Node for UiPassNode { impl Node for UiPassNode {
fn input(&self) -> Vec<SlotInfo> {
vec![SlotInfo::new(UiPassNode::IN_VIEW, SlotType::Entity)]
}
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
self.ui_view_query.update_archetypes(world); self.ui_view_query.update_archetypes(world);
self.default_camera_view_query.update_archetypes(world); self.default_camera_view_query.update_archetypes(world);
@ -52,7 +46,7 @@ impl Node for UiPassNode {
render_context: &mut RenderContext, render_context: &mut RenderContext,
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
let input_view_entity = graph.get_input_entity(Self::IN_VIEW)?; let input_view_entity = graph.view_entity();
let Ok((transparent_phase, target, camera_ui)) = let Ok((transparent_phase, target, camera_ui)) =
self.ui_view_query.get_manual(world, input_view_entity) self.ui_view_query.get_manual(world, input_view_entity)

View File

@ -15,7 +15,7 @@ use bevy::{
extract_component::{ extract_component::{
ComponentUniforms, ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin, ComponentUniforms, ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
}, },
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext, SlotInfo, SlotType}, render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext},
render_resource::{ render_resource::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor,
BindGroupLayoutEntry, BindingResource, BindingType, CachedRenderPipelineId, BindGroupLayoutEntry, BindingResource, BindingType, CachedRenderPipelineId,
@ -88,16 +88,6 @@ impl Plugin for PostProcessPlugin {
// Register the post process node in the 3d render graph // Register the post process node in the 3d render graph
core_3d_graph.add_node(PostProcessNode::NAME, node); core_3d_graph.add_node(PostProcessNode::NAME, node);
// A slot edge tells the render graph which input/output value should be passed to the node.
// In this case, the view entity, which is the entity associated with the
// camera on which the graph is running.
core_3d_graph.add_slot_edge(
core_3d_graph.input_node().id,
core_3d::graph::input::VIEW_ENTITY,
PostProcessNode::NAME,
PostProcessNode::IN_VIEW,
);
// We now need to add an edge between our node and the nodes from bevy // We now need to add an edge between our node and the nodes from bevy
// to make sure our node is ordered correctly relative to other nodes. // to make sure our node is ordered correctly relative to other nodes.
// //
@ -118,7 +108,6 @@ struct PostProcessNode {
} }
impl PostProcessNode { impl PostProcessNode {
pub const IN_VIEW: &str = "view";
pub const NAME: &str = "post_process"; pub const NAME: &str = "post_process";
fn new(world: &mut World) -> Self { fn new(world: &mut World) -> Self {
@ -129,14 +118,6 @@ impl PostProcessNode {
} }
impl Node for PostProcessNode { impl Node for PostProcessNode {
// This defines the input slot of the node and tells the render graph what
// we will need when running the node.
fn input(&self) -> Vec<SlotInfo> {
// In this case we tell the graph that our node will use the view entity.
// Currently, every node in bevy uses this pattern, so it's safe to just copy it.
vec![SlotInfo::new(PostProcessNode::IN_VIEW, SlotType::Entity)]
}
// This will run every frame before the run() method // This will run every frame before the run() method
// The important difference is that `self` is `mut` here // The important difference is that `self` is `mut` here
fn update(&mut self, world: &mut World) { fn update(&mut self, world: &mut World) {
@ -158,7 +139,7 @@ impl Node for PostProcessNode {
world: &World, world: &World,
) -> Result<(), NodeRunError> { ) -> Result<(), NodeRunError> {
// Get the entity of the view for the render graph where this node is running // Get the entity of the view for the render graph where this node is running
let view_entity = graph_context.get_input_entity(PostProcessNode::IN_VIEW)?; let view_entity = graph_context.view_entity();
// We get the data we need from the world based on the view entity passed to the node. // We get the data we need from the world based on the view entity passed to the node.
// The data is the query that was defined earlier in the [`PostProcessNode`] // The data is the query that was defined earlier in the [`PostProcessNode`]