mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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:
parent
353f2e0b37
commit
2c21d423fd
20 changed files with 63 additions and 239 deletions
|
@ -16,7 +16,7 @@ use bevy_render::{
|
|||
ComponentUniforms, DynamicUniformIndex, ExtractComponentPlugin, UniformComponentPlugin,
|
||||
},
|
||||
prelude::Color,
|
||||
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext},
|
||||
render_resource::*,
|
||||
renderer::{RenderContext, RenderDevice},
|
||||
texture::{CachedTexture, TextureCache},
|
||||
|
@ -83,12 +83,6 @@ impl Plugin for BloomPlugin {
|
|||
.get_sub_graph_mut(crate::core_3d::graph::NAME)
|
||||
.unwrap();
|
||||
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
|
||||
draw_3d_graph.add_node_edge(
|
||||
crate::core_3d::graph::node::MAIN_PASS,
|
||||
|
@ -108,12 +102,6 @@ impl Plugin for BloomPlugin {
|
|||
.get_sub_graph_mut(crate::core_2d::graph::NAME)
|
||||
.unwrap();
|
||||
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
|
||||
draw_2d_graph.add_node_edge(
|
||||
crate::core_2d::graph::node::MAIN_PASS,
|
||||
|
@ -141,8 +129,6 @@ pub struct BloomNode {
|
|||
}
|
||||
|
||||
impl BloomNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
view_query: QueryState::new(world),
|
||||
|
@ -151,10 +137,6 @@ impl 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) {
|
||||
self.view_query.update_archetypes(world);
|
||||
}
|
||||
|
@ -174,7 +156,7 @@ impl Node for BloomNode {
|
|||
let downsampling_pipeline_res = world.resource::<BloomDownsamplingPipeline>();
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
let uniforms = world.resource::<ComponentUniforms<BloomUniforms>>();
|
||||
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
|
||||
let view_entity = graph.view_entity();
|
||||
let Ok((
|
||||
camera,
|
||||
view_target,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_phase::RenderPhase,
|
||||
render_resource::{LoadOp, Operations, RenderPassDescriptor},
|
||||
renderer::RenderContext,
|
||||
|
@ -27,8 +27,6 @@ pub struct MainPass2dNode {
|
|||
}
|
||||
|
||||
impl MainPass2dNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
query: world.query_filtered(),
|
||||
|
@ -37,10 +35,6 @@ impl 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) {
|
||||
self.query.update_archetypes(world);
|
||||
}
|
||||
|
@ -51,7 +45,7 @@ impl Node for MainPass2dNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> 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) =
|
||||
if let Ok(result) = self.query.get_manual(world, view_entity) {
|
||||
result
|
||||
|
|
|
@ -25,7 +25,7 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_render::{
|
||||
camera::Camera,
|
||||
extract_component::ExtractComponentPlugin,
|
||||
render_graph::{EmptyNode, RenderGraph, SlotInfo, SlotType},
|
||||
render_graph::{EmptyNode, RenderGraph},
|
||||
render_phase::{
|
||||
batch_phase_system, sort_phase_system, BatchedPhaseItem, CachedRenderPipelinePhaseItem,
|
||||
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::END_MAIN_PASS_POST_PROCESSING, EmptyNode);
|
||||
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::TONEMAPPING,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_phase::RenderPhase,
|
||||
render_resource::{LoadOp, Operations, RenderPassDepthStencilAttachment, RenderPassDescriptor},
|
||||
renderer::RenderContext,
|
||||
|
@ -35,8 +35,6 @@ pub struct MainPass3dNode {
|
|||
}
|
||||
|
||||
impl MainPass3dNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
query: world.query_filtered(),
|
||||
|
@ -45,10 +43,6 @@ impl 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) {
|
||||
self.query.update_archetypes(world);
|
||||
}
|
||||
|
@ -59,7 +53,7 @@ impl Node for MainPass3dNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
|
||||
let view_entity = graph.view_entity();
|
||||
let Ok((
|
||||
camera,
|
||||
opaque_phase,
|
||||
|
|
|
@ -29,7 +29,7 @@ use bevy_render::{
|
|||
camera::{Camera, ExtractedCamera},
|
||||
extract_component::ExtractComponentPlugin,
|
||||
prelude::Msaa,
|
||||
render_graph::{EmptyNode, RenderGraph, SlotInfo, SlotType},
|
||||
render_graph::{EmptyNode, RenderGraph},
|
||||
render_phase::{
|
||||
sort_phase_system, CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem,
|
||||
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::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::MAIN_PASS, graph::node::TONEMAPPING);
|
||||
draw_3d_graph.add_node_edge(
|
||||
|
|
|
@ -99,13 +99,6 @@ impl Plugin for FxaaPlugin {
|
|||
|
||||
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(
|
||||
core_3d::graph::node::TONEMAPPING,
|
||||
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_slot_edge(
|
||||
graph.input_node().id,
|
||||
core_2d::graph::input::VIEW_ENTITY,
|
||||
core_2d::graph::node::FXAA,
|
||||
FxaaNode::IN_VIEW,
|
||||
);
|
||||
|
||||
graph.add_node_edge(
|
||||
core_2d::graph::node::TONEMAPPING,
|
||||
core_2d::graph::node::FXAA,
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::fxaa::{CameraFxaaPipeline, Fxaa, FxaaPipeline};
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_ecs::query::QueryState;
|
||||
use bevy_render::{
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_resource::{
|
||||
BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, FilterMode, Operations,
|
||||
PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor,
|
||||
|
@ -28,8 +28,6 @@ pub struct FxaaNode {
|
|||
}
|
||||
|
||||
impl FxaaNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
query: QueryState::new(world),
|
||||
|
@ -39,10 +37,6 @@ impl 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) {
|
||||
self.query.update_archetypes(world);
|
||||
}
|
||||
|
@ -53,7 +47,7 @@ impl Node for FxaaNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> 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 fxaa_pipeline = world.resource::<FxaaPipeline>();
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use bevy_app::{App, Plugin};
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext},
|
||||
renderer::RenderContext,
|
||||
view::{Msaa, ViewTarget},
|
||||
Render, RenderSet,
|
||||
|
@ -28,7 +28,6 @@ impl Plugin for MsaaWritebackPlugin {
|
|||
let msaa_writeback_3d = MsaaWritebackNode::new(&mut render_app.world);
|
||||
let mut graph = render_app.world.resource_mut::<RenderGraph>();
|
||||
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(
|
||||
crate::core_2d::graph::node::MSAA_WRITEBACK,
|
||||
msaa_writeback_2d,
|
||||
|
@ -37,16 +36,9 @@ impl Plugin for MsaaWritebackPlugin {
|
|||
crate::core_2d::graph::node::MSAA_WRITEBACK,
|
||||
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) {
|
||||
let input_node = core_3d.input_node().id;
|
||||
core_3d.add_node(
|
||||
crate::core_3d::graph::node::MSAA_WRITEBACK,
|
||||
msaa_writeback_3d,
|
||||
|
@ -55,12 +47,6 @@ impl Plugin for MsaaWritebackPlugin {
|
|||
crate::core_3d::graph::node::MSAA_WRITEBACK,
|
||||
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 {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
cameras: world.query(),
|
||||
|
@ -80,9 +64,6 @@ impl 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) {
|
||||
self.cameras.update_archetypes(world);
|
||||
}
|
||||
|
@ -92,7 +73,7 @@ impl Node for MsaaWritebackNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> 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) {
|
||||
let blit_pipeline = world.resource::<BlitPipeline>();
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
|
|
|
@ -3,7 +3,7 @@ use bevy_ecs::query::QueryState;
|
|||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
prelude::Color,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_phase::RenderPhase,
|
||||
render_resource::{
|
||||
LoadOp, Operations, RenderPassColorAttachment, RenderPassDepthStencilAttachment,
|
||||
|
@ -34,8 +34,6 @@ pub struct PrepassNode {
|
|||
}
|
||||
|
||||
impl PrepassNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
main_view_query: QueryState::new(world),
|
||||
|
@ -44,10 +42,6 @@ impl 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) {
|
||||
self.main_view_query.update_archetypes(world);
|
||||
}
|
||||
|
@ -58,7 +52,7 @@ impl Node for PrepassNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
|
||||
let view_entity = graph.view_entity();
|
||||
let Ok((
|
||||
camera,
|
||||
opaque_prepass_phase,
|
||||
|
|
|
@ -6,7 +6,7 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_ecs::query::QueryState;
|
||||
use bevy_render::{
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_resource::{
|
||||
BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, BufferId, LoadOp,
|
||||
Operations, PipelineCache, RenderPassColorAttachment, RenderPassDescriptor,
|
||||
|
@ -34,8 +34,6 @@ pub struct TonemappingNode {
|
|||
}
|
||||
|
||||
impl TonemappingNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
query: QueryState::new(world),
|
||||
|
@ -46,10 +44,6 @@ impl 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) {
|
||||
self.query.update_archetypes(world);
|
||||
}
|
||||
|
@ -60,7 +54,7 @@ impl Node for TonemappingNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> 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 tonemapping_pipeline = world.resource::<TonemappingPipeline>();
|
||||
let gpu_images = world.get_resource::<RenderAssets<Image>>().unwrap();
|
||||
|
|
|
@ -3,7 +3,7 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_ecs::query::QueryState;
|
||||
use bevy_render::{
|
||||
camera::{CameraOutputMode, ExtractedCamera},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_resource::{
|
||||
BindGroup, BindGroupDescriptor, BindGroupEntry, BindingResource, LoadOp, Operations,
|
||||
PipelineCache, RenderPassColorAttachment, RenderPassDescriptor, SamplerDescriptor,
|
||||
|
@ -27,8 +27,6 @@ pub struct UpscalingNode {
|
|||
}
|
||||
|
||||
impl UpscalingNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
query: QueryState::new(world),
|
||||
|
@ -38,10 +36,6 @@ impl 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) {
|
||||
self.query.update_archetypes(world);
|
||||
}
|
||||
|
@ -52,7 +46,7 @@ impl Node for UpscalingNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> 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 blit_pipeline = world.get_resource::<BlitPipeline>().unwrap();
|
||||
|
|
|
@ -294,11 +294,5 @@ impl Plugin for PbrPlugin {
|
|||
draw_3d_graph::node::SHADOW_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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use bevy_render::{
|
|||
color::Color,
|
||||
mesh::Mesh,
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
render_phase::{
|
||||
CachedRenderPipelinePhaseItem, DrawFunctionId, DrawFunctions, PhaseItem, RenderPhase,
|
||||
},
|
||||
|
@ -1697,8 +1697,6 @@ pub struct ShadowPassNode {
|
|||
}
|
||||
|
||||
impl ShadowPassNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
main_view_query: QueryState::new(world),
|
||||
|
@ -1708,10 +1706,6 @@ impl 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) {
|
||||
self.main_view_query.update_archetypes(world);
|
||||
self.view_light_query.update_archetypes(world);
|
||||
|
@ -1723,7 +1717,7 @@ impl Node for ShadowPassNode {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
) -> 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) {
|
||||
for view_light_entity in view_lights.lights.iter().copied() {
|
||||
let (view_light, shadow_phase) = self
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
camera::{ExtractedCamera, NormalizedRenderTarget, SortedCameras},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext, SlotValue},
|
||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||
renderer::RenderContext,
|
||||
view::ExtractedWindows,
|
||||
};
|
||||
|
@ -39,7 +39,8 @@ impl Node for CameraDriverNode {
|
|||
}
|
||||
graph.run_sub_graph(
|
||||
camera.render_graph.clone(),
|
||||
vec![SlotValue::Entity(sorted_camera.entity)],
|
||||
vec![],
|
||||
Some(sorted_camera.entity),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use thiserror::Error;
|
|||
pub struct RunSubGraph {
|
||||
pub name: Cow<'static, str>,
|
||||
pub inputs: Vec<SlotValue>,
|
||||
pub view_entity: Option<Entity>,
|
||||
}
|
||||
|
||||
/// The context with all graph information required to run a [`Node`](super::Node).
|
||||
|
@ -27,6 +28,11 @@ pub struct RenderGraphContext<'a> {
|
|||
inputs: &'a [SlotValue],
|
||||
outputs: &'a mut [Option<SlotValue>],
|
||||
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> {
|
||||
|
@ -43,6 +49,7 @@ impl<'a> RenderGraphContext<'a> {
|
|||
inputs,
|
||||
outputs,
|
||||
run_sub_graphs: Vec::new(),
|
||||
view_entity: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,11 +165,24 @@ impl<'a> RenderGraphContext<'a> {
|
|||
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.
|
||||
pub fn run_sub_graph(
|
||||
&mut self,
|
||||
name: impl Into<Cow<'static, str>>,
|
||||
inputs: Vec<SlotValue>,
|
||||
view_entity: Option<Entity>,
|
||||
) -> Result<(), RunSubGraphError> {
|
||||
let name = name.into();
|
||||
let sub_graph = self
|
||||
|
@ -193,7 +213,11 @@ impl<'a> RenderGraphContext<'a> {
|
|||
return Err(RunSubGraphError::SubGraphHasNoInputs(name));
|
||||
}
|
||||
|
||||
self.run_sub_graphs.push(RunSubGraph { name, inputs });
|
||||
self.run_sub_graphs.push(RunSubGraph {
|
||||
name,
|
||||
inputs,
|
||||
view_entity,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
define_atomic_id,
|
||||
render_graph::{
|
||||
Edge, InputSlotError, OutputSlotError, RenderGraphContext, RenderGraphError,
|
||||
RunSubGraphError, SlotInfo, SlotInfos, SlotType, SlotValue,
|
||||
RunSubGraphError, SlotInfo, SlotInfos,
|
||||
},
|
||||
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.
|
||||
pub struct RunGraphOnViewNode {
|
||||
graph_name: Cow<'static, str>,
|
||||
}
|
||||
|
||||
impl RunGraphOnViewNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
pub fn new<T: Into<Cow<'static, str>>>(graph_name: T) -> Self {
|
||||
Self {
|
||||
graph_name: graph_name.into(),
|
||||
|
@ -322,20 +321,13 @@ impl RunGraphOnViewNode {
|
|||
}
|
||||
|
||||
impl Node for RunGraphOnViewNode {
|
||||
fn input(&self) -> Vec<SlotInfo> {
|
||||
vec![SlotInfo::new(Self::IN_VIEW, SlotType::Entity)]
|
||||
}
|
||||
fn run(
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
_render_context: &mut RenderContext,
|
||||
_world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
|
||||
graph.run_sub_graph(
|
||||
self.graph_name.clone(),
|
||||
vec![SlotValue::Entity(view_entity)],
|
||||
)?;
|
||||
graph.run_sub_graph(self.graph_name.clone(), vec![], Some(graph.view_entity()))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bevy_ecs::world::World;
|
||||
use bevy_ecs::{prelude::Entity, world::World};
|
||||
#[cfg(feature = "trace")]
|
||||
use bevy_utils::tracing::info_span;
|
||||
use bevy_utils::HashMap;
|
||||
|
@ -59,7 +59,7 @@ impl RenderGraphRunner {
|
|||
world: &World,
|
||||
) -> Result<(), RenderGraphRunnerError> {
|
||||
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")]
|
||||
let _span = info_span!("submit_graph_commands").entered();
|
||||
|
@ -74,6 +74,7 @@ impl RenderGraphRunner {
|
|||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
inputs: &[SlotValue],
|
||||
view_entity: Option<Entity>,
|
||||
) -> Result<(), RenderGraphRunnerError> {
|
||||
let mut node_outputs: HashMap<NodeId, SmallVec<[SlotValue; 4]>> = HashMap::default();
|
||||
#[cfg(feature = "trace")]
|
||||
|
@ -175,6 +176,10 @@ impl RenderGraphRunner {
|
|||
smallvec![None; node_state.output_slots.len()];
|
||||
{
|
||||
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")]
|
||||
let _span = info_span!("node", name = node_state.type_name).entered();
|
||||
|
@ -192,6 +197,7 @@ impl RenderGraphRunner {
|
|||
render_context,
|
||||
world,
|
||||
&run_sub_graph.inputs,
|
||||
run_sub_graph.view_entity,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use bevy_render::{
|
|||
camera::Camera,
|
||||
color::Color,
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{RenderGraph, RunGraphOnViewNode, SlotInfo, SlotType},
|
||||
render_graph::{RenderGraph, RunGraphOnViewNode},
|
||||
render_phase::{sort_phase_system, AddRenderCommand, DrawFunctions, RenderPhase},
|
||||
render_resource::*,
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
|
@ -44,9 +44,6 @@ pub mod node {
|
|||
|
||||
pub mod draw_ui_graph {
|
||||
pub const NAME: &str = "draw_ui";
|
||||
pub mod input {
|
||||
pub const VIEW_ENTITY: &str = "view_entity";
|
||||
}
|
||||
pub mod node {
|
||||
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,
|
||||
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(
|
||||
bevy_core_pipeline::core_2d::graph::node::END_MAIN_PASS_POST_PROCESSING,
|
||||
draw_ui_graph::node::UI_PASS,
|
||||
|
@ -144,12 +135,6 @@ pub fn build_ui_render(app: &mut App) {
|
|||
draw_ui_graph::node::UI_PASS,
|
||||
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 mut ui_graph = RenderGraph::default();
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ pub struct UiPassNode {
|
|||
}
|
||||
|
||||
impl UiPassNode {
|
||||
pub const IN_VIEW: &'static str = "view";
|
||||
|
||||
pub fn new(world: &mut World) -> Self {
|
||||
Self {
|
||||
ui_view_query: world.query_filtered(),
|
||||
|
@ -37,10 +35,6 @@ impl 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) {
|
||||
self.ui_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,
|
||||
world: &World,
|
||||
) -> 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)) =
|
||||
self.ui_view_query.get_manual(world, input_view_entity)
|
||||
|
|
|
@ -15,7 +15,7 @@ use bevy::{
|
|||
extract_component::{
|
||||
ComponentUniforms, ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
|
||||
},
|
||||
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext, SlotInfo, SlotType},
|
||||
render_graph::{Node, NodeRunError, RenderGraph, RenderGraphContext},
|
||||
render_resource::{
|
||||
BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor,
|
||||
BindGroupLayoutEntry, BindingResource, BindingType, CachedRenderPipelineId,
|
||||
|
@ -88,16 +88,6 @@ impl Plugin for PostProcessPlugin {
|
|||
// Register the post process node in the 3d render graph
|
||||
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
|
||||
// to make sure our node is ordered correctly relative to other nodes.
|
||||
//
|
||||
|
@ -118,7 +108,6 @@ struct PostProcessNode {
|
|||
}
|
||||
|
||||
impl PostProcessNode {
|
||||
pub const IN_VIEW: &str = "view";
|
||||
pub const NAME: &str = "post_process";
|
||||
|
||||
fn new(world: &mut World) -> Self {
|
||||
|
@ -129,14 +118,6 @@ impl 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
|
||||
// The important difference is that `self` is `mut` here
|
||||
fn update(&mut self, world: &mut World) {
|
||||
|
@ -158,7 +139,7 @@ impl Node for PostProcessNode {
|
|||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
// 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.
|
||||
// The data is the query that was defined earlier in the [`PostProcessNode`]
|
||||
|
|
Loading…
Reference in a new issue