"base render graph": a common baseline graph
This commit is contained in:
parent
a4fe37add1
commit
5537eabb8c
@ -7,4 +7,4 @@ edition = "2018"
|
||||
[dependencies]
|
||||
bevy_core = { path = "../bevy_core" }
|
||||
|
||||
uuid = { version = "0.8", features = ["v4"] }
|
||||
uuid = { version = "0.8", features = ["v4", "serde"] }
|
@ -39,7 +39,7 @@ cgmath = "0.17"
|
||||
tracing-subscriber = "0.2"
|
||||
erased-serde = "0.3"
|
||||
serde = { version = "1", features = ["derive"]}
|
||||
uuid = { version = "0.8", features = ["v4"] }
|
||||
uuid = { version = "0.8", features = ["v4", "serde"] }
|
||||
tracing = "0.1"
|
||||
itertools = "0.8"
|
||||
rayon = "1.2"
|
||||
|
@ -11,4 +11,4 @@ serde_json = "1.0"
|
||||
type-uuid = "0.1"
|
||||
erased-serde = "0.3"
|
||||
serde = { version = "1", features = ["derive"]}
|
||||
uuid = { version = "0.8", features = ["v4"] }
|
||||
uuid = { version = "0.8", features = ["v4", "serde"] }
|
@ -39,7 +39,7 @@ serde_json = "1.0"
|
||||
type-uuid = "0.1"
|
||||
erased-serde = "0.3"
|
||||
serde = { version = "1", features = ["derive"]}
|
||||
uuid = { version = "0.8", features = ["v4"] }
|
||||
uuid = { version = "0.8", features = ["v4", "serde"] }
|
||||
tracing = "0.1"
|
||||
itertools = "0.8"
|
||||
rayon = "1.2"
|
||||
|
@ -1,105 +1,62 @@
|
||||
use crate::{
|
||||
material::StandardMaterial, nodes::LightsNode, passes::build_main_pass,
|
||||
pipelines::build_forward_pipeline,
|
||||
};
|
||||
use bevy_app::GetEventReader;
|
||||
use crate::{material::StandardMaterial, nodes::LightsNode, pipelines::build_forward_pipeline};
|
||||
use bevy_asset::AssetStorage;
|
||||
use bevy_render::{
|
||||
base_render_graph,
|
||||
draw_target::AssignedMeshesDrawTarget,
|
||||
pipeline::PipelineDescriptor,
|
||||
render_graph::{
|
||||
nodes::{
|
||||
AssetUniformNode, CameraNode, PassNode, UniformNode, WindowSwapChainNode,
|
||||
WindowTextureNode,
|
||||
},
|
||||
nodes::{AssetUniformNode, PassNode, UniformNode},
|
||||
RenderGraph,
|
||||
},
|
||||
shader::Shader,
|
||||
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||
};
|
||||
use bevy_transform::prelude::LocalToWorld;
|
||||
use bevy_window::{WindowCreated, WindowReference, WindowResized};
|
||||
use legion::prelude::Resources;
|
||||
|
||||
pub mod node {
|
||||
pub const LOCAL_TO_WORLD: &str = "local_to_world";
|
||||
pub const STANDARD_MATERIAL: &str = "standard_material";
|
||||
pub const LIGHTS: &str = "lights";
|
||||
}
|
||||
|
||||
pub trait ForwardPbrRenderGraphBuilder {
|
||||
fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ForwardPbrRenderGraphBuilder for RenderGraph {
|
||||
fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||
self.add_system_node_named("camera", CameraNode::default(), resources);
|
||||
self.add_system_node_named(
|
||||
"local_to_world",
|
||||
node::LOCAL_TO_WORLD,
|
||||
UniformNode::<LocalToWorld>::new(true),
|
||||
resources,
|
||||
);
|
||||
self.add_system_node_named(
|
||||
"standard_material",
|
||||
node::STANDARD_MATERIAL,
|
||||
AssetUniformNode::<StandardMaterial>::new(true),
|
||||
resources,
|
||||
);
|
||||
self.add_system_node_named("lights", LightsNode::new(10), resources);
|
||||
self.add_node_named(
|
||||
"swapchain",
|
||||
WindowSwapChainNode::new(
|
||||
WindowReference::Primary,
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
),
|
||||
);
|
||||
self.add_node_named(
|
||||
"main_pass_depth_texture",
|
||||
WindowTextureNode::new(
|
||||
WindowReference::Primary,
|
||||
TextureDescriptor {
|
||||
size: Extent3d {
|
||||
depth: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
},
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Depth32Float, // PERF: vulkan docs recommend using 24 bit depth for better performance
|
||||
usage: TextureUsage::OUTPUT_ATTACHMENT,
|
||||
},
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
),
|
||||
);
|
||||
self.add_system_node_named(node::LIGHTS, LightsNode::new(10), resources);
|
||||
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
let mut pipelines = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut main_pass = PassNode::new(build_main_pass());
|
||||
main_pass.add_pipeline(
|
||||
pipelines.add_default(build_forward_pipeline(&mut shaders)),
|
||||
vec![Box::new(AssignedMeshesDrawTarget)],
|
||||
);
|
||||
self.add_node_named("main_pass", main_pass);
|
||||
{
|
||||
let main_pass: &mut PassNode = self
|
||||
.get_node_mut(base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
main_pass.add_pipeline(
|
||||
pipelines.add_default(build_forward_pipeline(&mut shaders)),
|
||||
vec![Box::new(AssignedMeshesDrawTarget)],
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: replace these with "autowire" groups
|
||||
self.add_node_edge("camera", "main_pass").unwrap();
|
||||
self.add_node_edge("standard_material", "main_pass")
|
||||
self.add_node_edge(node::STANDARD_MATERIAL, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
self.add_node_edge(node::LOCAL_TO_WORLD, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
self.add_node_edge(node::LIGHTS, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
self.add_node_edge("local_to_world", "main_pass").unwrap();
|
||||
self.add_node_edge("lights", "main_pass").unwrap();
|
||||
self.add_slot_edge(
|
||||
"swapchain",
|
||||
WindowSwapChainNode::OUT_TEXTURE,
|
||||
"main_pass",
|
||||
"color",
|
||||
)
|
||||
.unwrap();
|
||||
self.add_slot_edge(
|
||||
"main_pass_depth_texture",
|
||||
WindowTextureNode::OUT_TEXTURE,
|
||||
"main_pass",
|
||||
"depth",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ pub mod entity;
|
||||
pub mod light;
|
||||
pub mod material;
|
||||
pub mod nodes;
|
||||
pub mod passes;
|
||||
pub mod pipelines;
|
||||
|
||||
mod forward_pbr_render_graph;
|
||||
@ -14,10 +13,10 @@ use bevy_render::{render_graph::RenderGraph, shader};
|
||||
use legion::prelude::IntoSystem;
|
||||
use material::StandardMaterial;
|
||||
|
||||
/// NOTE: this isn't PBR yet. consider this name "aspirational" :)
|
||||
#[derive(Default)]
|
||||
pub struct PbrPlugin;
|
||||
|
||||
// NOTE: this isn't PBR yet. consider this name "aspirational" :)
|
||||
impl AppPlugin for PbrPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.add_resource(AssetStorage::<StandardMaterial>::new())
|
||||
|
@ -1,28 +0,0 @@
|
||||
use bevy_render::pass::{
|
||||
LoadOp, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, StoreOp, TextureAttachment,
|
||||
};
|
||||
|
||||
use bevy_render::Color;
|
||||
|
||||
pub fn build_main_pass() -> PassDescriptor {
|
||||
PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("color".to_string()),
|
||||
resolve_target: None,
|
||||
load_op: LoadOp::Clear,
|
||||
store_op: StoreOp::Store,
|
||||
clear_color: Color::rgb(0.1, 0.1, 0.1),
|
||||
}],
|
||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("depth".to_string()),
|
||||
depth_load_op: LoadOp::Clear,
|
||||
depth_store_op: StoreOp::Store,
|
||||
stencil_load_op: LoadOp::Clear,
|
||||
stencil_store_op: StoreOp::Store,
|
||||
clear_depth: 1.0,
|
||||
clear_stencil: 0,
|
||||
}),
|
||||
sample_count: 1,
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
mod main;
|
||||
|
||||
pub use main::*;
|
155
crates/bevy_render/src/base_render_graph/mod.rs
Normal file
155
crates/bevy_render/src/base_render_graph/mod.rs
Normal file
@ -0,0 +1,155 @@
|
||||
use crate::{
|
||||
pass::{
|
||||
LoadOp, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, StoreOp, TextureAttachment,
|
||||
},
|
||||
render_graph::{
|
||||
nodes::{
|
||||
Camera2dNode, CameraNode, PassNode, WindowSwapChainNode,
|
||||
WindowTextureNode,
|
||||
},
|
||||
RenderGraph,
|
||||
},
|
||||
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||
Color,
|
||||
};
|
||||
use bevy_app::GetEventReader;
|
||||
use bevy_window::{WindowCreated, WindowReference, WindowResized};
|
||||
use legion::prelude::Resources;
|
||||
|
||||
pub struct BaseRenderGraphConfig {
|
||||
add_2d_camera: bool,
|
||||
add_3d_camera: bool,
|
||||
add_main_pass: bool,
|
||||
connect_main_pass_to_swapchain: bool,
|
||||
}
|
||||
|
||||
pub mod node {
|
||||
pub const PRIMARY_SWAP_CHAIN: &str = "swapchain";
|
||||
pub const CAMERA: &str = "camera";
|
||||
pub const CAMERA2D: &str = "camera2d";
|
||||
pub const MAIN_PASS_DEPTH_TEXTURE: &str = "main_pass_depth_texture";
|
||||
pub const MAIN_PASS: &str = "main_pass";
|
||||
}
|
||||
|
||||
impl Default for BaseRenderGraphConfig {
|
||||
fn default() -> Self {
|
||||
BaseRenderGraphConfig {
|
||||
add_2d_camera: true,
|
||||
add_3d_camera: true,
|
||||
add_main_pass: true,
|
||||
connect_main_pass_to_swapchain: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// The "base render graph" provides a core set of render graph nodes which can be used to build any graph.
|
||||
/// By itself this graph doesn't do much, but it allows Render plugins to interop with each other by having a common
|
||||
/// set of nodes. It can be customized using `BaseRenderGraphConfig`.
|
||||
pub trait BaseRenderGraphBuilder {
|
||||
fn add_base_graph(
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
config: &BaseRenderGraphConfig,
|
||||
) -> &mut Self;
|
||||
}
|
||||
|
||||
impl BaseRenderGraphBuilder for RenderGraph {
|
||||
fn add_base_graph(
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
config: &BaseRenderGraphConfig,
|
||||
) -> &mut Self {
|
||||
if config.add_3d_camera {
|
||||
self.add_system_node_named(node::CAMERA, CameraNode::default(), resources);
|
||||
}
|
||||
|
||||
if config.add_2d_camera {
|
||||
self.add_system_node_named(node::CAMERA2D, Camera2dNode::default(), resources);
|
||||
}
|
||||
|
||||
if config.add_main_pass {
|
||||
self.add_node_named(
|
||||
node::MAIN_PASS_DEPTH_TEXTURE,
|
||||
WindowTextureNode::new(
|
||||
WindowReference::Primary,
|
||||
TextureDescriptor {
|
||||
size: Extent3d {
|
||||
depth: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
},
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Depth32Float, // PERF: vulkan docs recommend using 24 bit depth for better performance
|
||||
usage: TextureUsage::OUTPUT_ATTACHMENT,
|
||||
},
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
),
|
||||
);
|
||||
|
||||
self.add_node_named(
|
||||
node::MAIN_PASS,
|
||||
PassNode::new(PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("color".to_string()),
|
||||
resolve_target: None,
|
||||
load_op: LoadOp::Clear,
|
||||
store_op: StoreOp::Store,
|
||||
clear_color: Color::rgb(0.1, 0.1, 0.1),
|
||||
}],
|
||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("depth".to_string()),
|
||||
depth_load_op: LoadOp::Clear,
|
||||
depth_store_op: StoreOp::Store,
|
||||
stencil_load_op: LoadOp::Clear,
|
||||
stencil_store_op: StoreOp::Store,
|
||||
clear_depth: 1.0,
|
||||
clear_stencil: 0,
|
||||
}),
|
||||
sample_count: 1,
|
||||
}),
|
||||
);
|
||||
|
||||
self.add_slot_edge(
|
||||
node::MAIN_PASS_DEPTH_TEXTURE,
|
||||
WindowTextureNode::OUT_TEXTURE,
|
||||
node::MAIN_PASS,
|
||||
"depth",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if config.add_3d_camera {
|
||||
self.add_node_edge(node::CAMERA, node::MAIN_PASS).unwrap();
|
||||
}
|
||||
|
||||
if config.add_2d_camera {
|
||||
self.add_node_edge(node::CAMERA2D, node::MAIN_PASS).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.add_node_named(
|
||||
node::PRIMARY_SWAP_CHAIN,
|
||||
WindowSwapChainNode::new(
|
||||
WindowReference::Primary,
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
),
|
||||
);
|
||||
|
||||
if config.connect_main_pass_to_swapchain {
|
||||
self.add_slot_edge(
|
||||
node::PRIMARY_SWAP_CHAIN,
|
||||
WindowSwapChainNode::OUT_TEXTURE,
|
||||
node::MAIN_PASS,
|
||||
"color",
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ pub use renderable::*;
|
||||
|
||||
pub use vertex::Vertex;
|
||||
|
||||
pub mod base_render_graph;
|
||||
pub mod draw_target;
|
||||
pub mod pass;
|
||||
pub mod pipeline;
|
||||
@ -38,6 +39,7 @@ use self::{
|
||||
texture::Texture,
|
||||
};
|
||||
|
||||
use base_render_graph::{BaseRenderGraphBuilder, BaseRenderGraphConfig};
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin};
|
||||
use bevy_asset::AssetStorage;
|
||||
use mesh::mesh_resource_provider_system;
|
||||
@ -46,17 +48,30 @@ use render_graph::RenderGraph;
|
||||
pub static RENDER_RESOURCE_STAGE: &str = "render_resource";
|
||||
pub static RENDER_STAGE: &str = "render";
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderPlugin;
|
||||
pub struct RenderPlugin {
|
||||
/// configures the "base render graph". If this is not `None`, the "base render graph" will be added
|
||||
pub base_render_graph_config: Option<BaseRenderGraphConfig>,
|
||||
}
|
||||
|
||||
impl RenderPlugin {}
|
||||
impl Default for RenderPlugin {
|
||||
fn default() -> Self {
|
||||
RenderPlugin {
|
||||
base_render_graph_config: Some(BaseRenderGraphConfig::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AppPlugin for RenderPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
let mut render_graph = RenderGraph::default();
|
||||
if let Some(ref config) = self.base_render_graph_config {
|
||||
render_graph.add_base_graph(app.resources(), config);
|
||||
}
|
||||
|
||||
app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE)
|
||||
.add_stage_after(RENDER_RESOURCE_STAGE, RENDER_STAGE)
|
||||
// resources
|
||||
.add_resource(RenderGraph::default())
|
||||
.add_resource(render_graph)
|
||||
.add_resource(AssetStorage::<Mesh>::new())
|
||||
.add_resource(AssetStorage::<Texture>::new())
|
||||
.add_resource(AssetStorage::<Shader>::new())
|
||||
|
@ -9,4 +9,4 @@ legion = { path = "../bevy_legion", features = ["serialize"] }
|
||||
serde = { version = "1", features = ["derive"]}
|
||||
erased-serde = "0.3"
|
||||
type-uuid = "0.1"
|
||||
uuid = { version = "0.8", features = ["v4"] }
|
||||
uuid = { version = "0.8", features = ["v4", "serde"] }
|
Loading…
Reference in New Issue
Block a user