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
@ -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,
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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>();
|
||||||
|
|
||||||
|
|||||||
@ -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>();
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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`]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user