From ec84a33b438a6e7d06b677ba2a27daec67acad6b Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sat, 28 Mar 2020 23:18:33 -0700 Subject: [PATCH] everything is a plugin ... well almost everything --- examples/custom_shader.rs | 102 ++++---- examples/entity_builder_comparison.rs | 2 +- examples/instancing.rs | 8 +- examples/instancing_old.rs | 2 +- examples/parenting.rs | 2 +- .../plugin_loading/example_plugin/src/lib.rs | 2 +- examples/serializing.rs | 2 +- examples/simple.rs | 2 +- examples/spawner.rs | 8 +- examples/texture.rs | 2 +- examples/ui.rs | 2 +- examples/ui_bench.rs | 8 +- src/app/app.rs | 2 +- src/app/app_builder.rs | 221 +++++------------- src/core/core_plugin.rs | 15 ++ src/core/mod.rs | 2 + src/diagnostic/diagnostic_plugin.rs | 43 ++++ src/diagnostic/mod.rs | 2 + src/plugin/mod.rs | 2 +- src/prelude.rs | 2 + src/render/mod.rs | 2 + src/render/pass/passes/forward.rs | 2 +- src/render/pipeline/pipelines/forward/mod.rs | 2 +- .../pipeline/pipelines/forward_flat/mod.rs | 2 +- src/render/pipeline/pipelines/ui/mod.rs | 2 +- src/render/render_graph/render_graph.rs | 15 +- .../render_graph/render_graph_builder.rs | 49 +--- src/render/render_plugin.rs | 78 +++++++ .../wgpu_renderer/wgpu_render_pass.rs | 37 ++- 29 files changed, 331 insertions(+), 289 deletions(-) create mode 100644 src/core/core_plugin.rs create mode 100644 src/diagnostic/diagnostic_plugin.rs create mode 100644 src/render/render_plugin.rs diff --git a/examples/custom_shader.rs b/examples/custom_shader.rs index ca9bd838b3..3b8aa307c7 100644 --- a/examples/custom_shader.rs +++ b/examples/custom_shader.rs @@ -1,5 +1,9 @@ use bevy::prelude::*; +fn main() { + App::build().add_defaults().setup(setup).run(); +} + #[derive(Uniforms, Default)] struct MyMaterial { pub color: Color, @@ -7,58 +11,54 @@ struct MyMaterial { pub always_red: bool, } -fn main() { - App::build() - .add_defaults() - .setup_render_graph(|render_graph_builder| { - render_graph_builder - .add_resource_provider(UniformResourceProvider::::new(true)) - .add_pipeline_to_pass(resource_name::pass::MAIN, "MyMaterial", |builder| { - builder - .with_vertex_shader(Shader::from_glsl( - ShaderStage::Vertex, - r#" - #version 450 - layout(location = 0) in vec4 Vertex_Position; - layout(location = 0) out vec4 v_Position; - layout(set = 0, binding = 0) uniform Camera { - mat4 ViewProj; - }; - layout(set = 1, binding = 0) uniform Object { - mat4 Model; - }; - void main() { - v_Position = Model * Vertex_Position; - gl_Position = ViewProj * v_Position; - } - "#, - )) - .with_fragment_shader(Shader::from_glsl( - ShaderStage::Fragment, - r#" - #version 450 - layout(location = 0) in vec4 v_Position; - layout(location = 0) out vec4 o_Target; - layout(set = 1, binding = 1) uniform MyMaterial_color { - vec4 color; - }; - void main() { - o_Target = color; - - # ifdef MYMATERIAL_ALWAYS_RED - o_Target = vec4(0.8, 0.0, 0.0, 1.0); - # endif - } - "#, - )) - .with_default_config(); - }); - }) - .setup_world(setup) - .run(); -} - fn setup(world: &mut World, resources: &mut Resources) { + let mut render_graph = resources.get_mut::().unwrap(); + let mut pipelines = resources.get_mut::>().unwrap(); + let mut shaders = resources.get_mut::>().unwrap(); + render_graph + .build(&mut pipelines, &mut shaders) + .add_resource_provider(UniformResourceProvider::::new(true)) + .add_pipeline_to_pass(resource_name::pass::MAIN, "MyMaterial", |builder| { + builder + .with_vertex_shader(Shader::from_glsl( + ShaderStage::Vertex, + r#" + #version 450 + layout(location = 0) in vec4 Vertex_Position; + layout(location = 0) out vec4 v_Position; + layout(set = 0, binding = 0) uniform Camera { + mat4 ViewProj; + }; + layout(set = 1, binding = 0) uniform Object { + mat4 Model; + }; + void main() { + v_Position = Model * Vertex_Position; + gl_Position = ViewProj * v_Position; + } + "#, + )) + .with_fragment_shader(Shader::from_glsl( + ShaderStage::Fragment, + r#" + #version 450 + layout(location = 0) in vec4 v_Position; + layout(location = 0) out vec4 o_Target; + layout(set = 1, binding = 1) uniform MyMaterial_color { + vec4 color; + }; + void main() { + o_Target = color; + + # ifdef MYMATERIAL_ALWAYS_RED + o_Target = vec4(0.8, 0.0, 0.0, 1.0); + # endif + } + "#, + )) + .with_default_config(); + }); + let mut mesh_storage = resources.get_mut::>().unwrap(); let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube)); diff --git a/examples/entity_builder_comparison.rs b/examples/entity_builder_comparison.rs index a754053903..e4ab9113e4 100644 --- a/examples/entity_builder_comparison.rs +++ b/examples/entity_builder_comparison.rs @@ -1,7 +1,7 @@ use bevy::prelude::*; fn main() { - App::build().add_defaults().setup_world(setup).run(); + App::build().add_defaults().setup(setup).run(); } #[allow(dead_code)] diff --git a/examples/instancing.rs b/examples/instancing.rs index d72fac93f6..209b95875c 100644 --- a/examples/instancing.rs +++ b/examples/instancing.rs @@ -5,9 +5,11 @@ fn main() { App::build() .add_defaults() .add_system(build_move_system()) - .add_default_diagnostics() - .print_diagnostics() - .setup_world(setup) + .add_plugin(DiagnosticsPlugin { + print_diagnostics: true, + ..Default::default() + }) + .setup(setup) .run(); } diff --git a/examples/instancing_old.rs b/examples/instancing_old.rs index 890c819221..bf2909d63a 100644 --- a/examples/instancing_old.rs +++ b/examples/instancing_old.rs @@ -20,7 +20,7 @@ struct Wander { fn main() { App::build() - .setup_world(setup) + .setup(setup) .add_system(build_wander_system()) .add_system(build_navigate_system()) .add_system(build_move_system()) diff --git a/examples/parenting.rs b/examples/parenting.rs index 8d10965bbf..47e3207d41 100644 --- a/examples/parenting.rs +++ b/examples/parenting.rs @@ -5,7 +5,7 @@ struct Rotator; fn main() { App::build() .add_defaults() - .setup_world(setup) + .setup(setup) .add_system(build_rotator_system()) .run(); } diff --git a/examples/plugin_loading/example_plugin/src/lib.rs b/examples/plugin_loading/example_plugin/src/lib.rs index 221a459650..fc2cb7d84e 100644 --- a/examples/plugin_loading/example_plugin/src/lib.rs +++ b/examples/plugin_loading/example_plugin/src/lib.rs @@ -5,7 +5,7 @@ pub struct ExamplePlugin; impl AppPlugin for ExamplePlugin { fn build(&self, app_builder: AppBuilder) -> AppBuilder { - app_builder.setup_world(setup) + app_builder.setup(setup) } fn name(&self) -> &'static str { diff --git a/examples/serializing.rs b/examples/serializing.rs index b894db14e4..b701b9c8f5 100644 --- a/examples/serializing.rs +++ b/examples/serializing.rs @@ -2,7 +2,7 @@ use bevy::{prelude::*, serialization::*}; use serde::{Deserialize, Serialize}; use type_uuid::TypeUuid; fn main() { - let app = App::build().add_defaults().setup_world(setup).build(); + let app = App::build().add_defaults().setup(setup).build(); let comp_registrations = [ComponentRegistration::of::()]; diff --git a/examples/simple.rs b/examples/simple.rs index 1d81f008b0..20cf2fce3c 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,7 +1,7 @@ use bevy::prelude::*; fn main() { - App::build().add_defaults().setup_world(setup).run(); + App::build().add_defaults().setup(setup).run(); } fn setup(world: &mut World, resources: &mut Resources) { diff --git a/examples/spawner.rs b/examples/spawner.rs index e62482d24c..66ab7e77e7 100644 --- a/examples/spawner.rs +++ b/examples/spawner.rs @@ -5,9 +5,11 @@ fn main() { App::build() .add_defaults() .add_system(build_move_system()) - .add_default_diagnostics() - .print_diagnostics() - .setup_world(setup) + .add_plugin(DiagnosticsPlugin { + print_diagnostics: true, + ..Default::default() + }) + .setup(setup) .run(); } diff --git a/examples/texture.rs b/examples/texture.rs index 3348c3a8fa..e03ae14b75 100644 --- a/examples/texture.rs +++ b/examples/texture.rs @@ -1,7 +1,7 @@ use bevy::prelude::*; fn main() { - App::build().add_defaults().setup_world(setup).run(); + App::build().add_defaults().setup(setup).run(); } fn setup(world: &mut World, resources: &mut Resources) { diff --git a/examples/ui.rs b/examples/ui.rs index a5e90938b6..11f74352e0 100644 --- a/examples/ui.rs +++ b/examples/ui.rs @@ -1,7 +1,7 @@ use bevy::prelude::*; fn main() { - App::build().add_defaults().setup_world(setup).run(); + App::build().add_defaults().setup(setup).run(); } fn setup(world: &mut World, resources: &mut Resources) { diff --git a/examples/ui_bench.rs b/examples/ui_bench.rs index 8390a390b1..555487859c 100644 --- a/examples/ui_bench.rs +++ b/examples/ui_bench.rs @@ -3,10 +3,12 @@ use bevy::prelude::*; fn main() { App::build() .add_defaults() - .setup_world(setup) + .setup(setup) .add_system(build_move_system()) - .add_default_diagnostics() - .print_diagnostics() + .add_plugin(DiagnosticsPlugin { + print_diagnostics: true, + ..Default::default() + }) .run(); } diff --git a/src/app/app.rs b/src/app/app.rs index 70ac5e7908..e5e3e960e6 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -14,8 +14,8 @@ impl App { pub fn new( universe: Universe, world: World, - schedule: Schedule, resources: Resources, + schedule: Schedule, run: Option>, renderer: Option>, ) -> App { diff --git a/src/app/app_builder.rs b/src/app/app_builder.rs index d713c6e2c0..be44ff27cb 100644 --- a/src/app/app_builder.rs +++ b/src/app/app_builder.rs @@ -1,35 +1,22 @@ use crate::{ app::{system_stage, App}, - asset::*, - core::{window::winit::get_winit_run, Time, Window}, - diagnostic::{diagnostics, Diagnostics}, + core::{window::winit::get_winit_run, CorePlugin}, legion::prelude::{Resources, Runnable, Schedulable, Schedule, Universe, World}, - plugin::load_plugin, - prelude::StandardMaterial, - render::{ - draw_target::draw_targets::*, mesh::Mesh, pass::passes::*, pipeline::pipelines::*, - render_resource::resource_providers::*, renderer::Renderer, texture::Texture, *, - }, + plugin::{load_plugin, AppPlugin}, + render::{renderer::Renderer, *}, ui, }; -use bevy_transform::{prelude::LocalToWorld, transform_system_bundle}; -use pipeline::{PipelineCompiler, PipelineDescriptor, ShaderPipelineAssignments}; -use render_graph::{RenderGraph, RenderGraphBuilder}; -use render_resource::{ - build_entity_render_resource_assignments_system, AssetBatchers, - EntityRenderResourceAssignments, RenderResourceAssignments, -}; -use shader::Shader; -use std::{collections::HashMap, time::Duration}; +use bevy_transform::transform_system_bundle; +use render_resource::build_entity_render_resource_assignments_system; +use std::collections::HashMap; pub struct AppBuilder { - pub world: Option, - pub resources: Option, - pub universe: Option, + pub world: World, + pub resources: Resources, + pub universe: Universe, pub renderer: Option>, pub run: Option>, - pub render_graph: Option, pub setup_systems: Vec>, pub system_stages: HashMap>>, pub runnable_stages: HashMap>>, @@ -42,10 +29,9 @@ impl AppBuilder { let world = universe.create_world(); let resources = Resources::default(); AppBuilder { - universe: Some(universe), - world: Some(world), - resources: Some(resources), - render_graph: Some(RenderGraph::default()), + universe, + world, + resources, renderer: None, run: None, setup_systems: Vec::new(), @@ -55,17 +41,14 @@ impl AppBuilder { } } - pub fn build(&mut self) -> App { + pub fn build(mut self) -> App { let mut setup_schedule_builder = Schedule::builder(); for setup_system in self.setup_systems.drain(..) { setup_schedule_builder = setup_schedule_builder.add_system(setup_system); } let mut setup_schedule = setup_schedule_builder.build(); - setup_schedule.execute( - self.world.as_mut().unwrap(), - self.resources.as_mut().unwrap(), - ); + setup_schedule.execute(&mut self.world, &mut self.resources); let mut schedule_builder = Schedule::builder(); for stage_name in self.stage_order.iter() { @@ -86,52 +69,40 @@ impl AppBuilder { } } - self.resources - .as_mut() - .unwrap() - .insert(self.render_graph.take().unwrap()); - App::new( - self.universe.take().unwrap(), - self.world.take().unwrap(), + self.universe, + self.world, + self.resources, schedule_builder.build(), - self.resources.take().unwrap(), self.run.take(), self.renderer.take(), ) } - pub fn run(&mut self) { + pub fn run(self) { self.build().run(); } - pub fn with_world(&mut self, world: World) -> &mut Self { - self.world = Some(world); + pub fn with_world(mut self, world: World) -> Self { + self.world = world; self } - pub fn setup_world(&mut self, setup: impl Fn(&mut World, &mut Resources)) -> &mut Self { - setup( - self.world.as_mut().unwrap(), - self.resources.as_mut().unwrap(), - ); + pub fn setup(mut self, setup: impl Fn(&mut World, &mut Resources)) -> Self { + setup(&mut self.world, &mut self.resources); self } - pub fn add_system(&mut self, system: Box) -> &mut Self { + pub fn add_system(self, system: Box) -> Self { self.add_system_to_stage(system_stage::UPDATE, system) } - pub fn add_setup_system(&mut self, system: Box) -> &mut Self { + pub fn add_setup_system(mut self, system: Box) -> Self { self.setup_systems.push(system); self } - pub fn add_system_to_stage( - &mut self, - stage_name: &str, - system: Box, - ) -> &mut Self { + pub fn add_system_to_stage(mut self, stage_name: &str, system: Box) -> Self { if let None = self.system_stages.get(stage_name) { self.system_stages .insert(stage_name.to_string(), Vec::new()); @@ -144,11 +115,7 @@ impl AppBuilder { self } - pub fn add_runnable_to_stage( - &mut self, - stage_name: &str, - system: Box, - ) -> &mut Self { + pub fn add_runnable_to_stage(mut self, stage_name: &str, system: Box) -> Self { if let None = self.runnable_stages.get(stage_name) { self.runnable_stages .insert(stage_name.to_string(), Vec::new()); @@ -161,111 +128,27 @@ impl AppBuilder { self } - pub fn add_default_resources(&mut self) -> &mut Self { - let resources = self.resources.as_mut().unwrap(); - resources.insert(Window::default()); - resources.insert(Time::new()); - resources.insert(Diagnostics::default()); - resources.insert(AssetStorage::::new()); - resources.insert(AssetStorage::::new()); - resources.insert(AssetStorage::::new()); - resources.insert(AssetStorage::::new()); - resources.insert(AssetStorage::::new()); - resources.insert(ShaderPipelineAssignments::new()); - resources.insert(PipelineCompiler::new()); - resources.insert(RenderResourceAssignments::default()); - resources.insert(EntityRenderResourceAssignments::default()); - self.batch_types2::(); - self - } - - pub fn add_default_diagnostics(&mut self) -> &mut Self { - let frame_time_diagnostic_system = { - let resources = self.resources.as_mut().unwrap(); - diagnostics::frame_time_diagnostic_system(resources, 10) - }; - self.add_system(frame_time_diagnostic_system) - } - - pub fn print_diagnostics(&mut self) -> &mut Self { - self.add_system(diagnostics::print_diagnostics_system( - Duration::from_secs_f64(1.0), - )) - } - - pub fn print_diagnostics_with_wait(&mut self, wait: Duration) -> &mut Self { - self.add_system(diagnostics::print_diagnostics_system(wait)) - } - - pub fn batch_types2(&mut self) -> &mut Self + pub fn add_resource(mut self, resource: T) -> Self where - T1: 'static, - T2: 'static, + T: Send + Sync + 'static, { - { - let resources = self.resources.as_mut().unwrap(); - let mut asset_batchers = resources - .get_mut_or_insert_with(|| AssetBatchers::default()) - .unwrap(); - - asset_batchers.batch_types2::(); - } - + self.resources.insert(resource); self } - pub fn add_default_systems(&mut self) -> &mut Self { - self.add_system(build_entity_render_resource_assignments_system()); - self.add_system(ui::ui_update_system::build_ui_update_system()); - for transform_system in - transform_system_bundle::build(self.world.as_mut().unwrap()).drain(..) - { - self.add_system(transform_system); - } - - self - } - - pub fn add_render_graph_defaults(&mut self) -> &mut Self { - self.setup_render_graph(|builder| { - builder - .add_draw_target(MeshesDrawTarget::default()) - .add_draw_target(AssignedBatchesDrawTarget::default()) - .add_draw_target(AssignedMeshesDrawTarget::default()) - .add_draw_target(UiDrawTarget::default()) - .add_resource_provider(CameraResourceProvider::default()) - .add_resource_provider(Camera2dResourceProvider::default()) - .add_resource_provider(LightResourceProvider::new(10)) - .add_resource_provider(UiResourceProvider::new()) - .add_resource_provider(MeshResourceProvider::new()) - .add_resource_provider(UniformResourceProvider::::new(true)) - .add_resource_provider(UniformResourceProvider::::new(true)) - .add_forward_pass() - .add_forward_pipeline(); - // .add_ui_pipeline(); - }) - } - - pub fn setup_render_graph<'a>( - &'a mut self, - setup: impl Fn(&'_ mut RenderGraphBuilder<'_>), - ) -> &'a mut Self { - { - let mut render_graph_builder = self - .render_graph - .take() - .unwrap() - .build(self.resources.as_mut().unwrap()); - setup(&mut render_graph_builder); - - self.render_graph = Some(render_graph_builder.finish()); + pub fn add_default_systems(mut self) -> Self { + self = self + .add_system(build_entity_render_resource_assignments_system()) + .add_system(ui::ui_update_system::build_ui_update_system()); + for transform_system in transform_system_bundle::build(&mut self.world).drain(..) { + self = self.add_system(transform_system); } self } #[cfg(feature = "wgpu")] - pub fn add_wgpu_renderer(&mut self) -> &mut Self { + pub fn add_wgpu_renderer(mut self) -> Self { self.renderer = Some(Box::new( renderer::renderers::wgpu_renderer::WgpuRenderer::new(), )); @@ -273,32 +156,42 @@ impl AppBuilder { } #[cfg(not(feature = "wgpu"))] - fn add_wgpu_renderer(&mut self) -> &mut Self { + fn add_wgpu_renderer(mut self) -> Self { self } #[cfg(feature = "winit")] - pub fn add_winit(&mut self) -> &mut Self { + pub fn add_winit(mut self) -> Self { self.run = Some(get_winit_run()); self } #[cfg(not(feature = "winit"))] - pub fn add_winit(&mut self) -> &mut Self { + pub fn add_winit(mut self) -> Self { self } - pub fn add_defaults(&mut self) -> &mut Self { - self.add_winit() - .add_default_resources() + pub fn add_defaults(mut self) -> Self { + self = self + .add_winit() .add_default_systems() - .add_render_graph_defaults() - .add_wgpu_renderer() + .add_plugin(CorePlugin::default()) + .add_plugin(RenderPlugin::default()) + .add_wgpu_renderer(); + #[cfg(feature = "winit")] + {} + self } - pub fn load_plugin(&mut self, path: &str) -> &mut Self { + pub fn load_plugin(self, path: &str) -> Self { let (_lib, plugin) = load_plugin(path); - plugin.build(self); - self + plugin.build(self) + } + + pub fn add_plugin(self, plugin: T) -> Self + where + T: AppPlugin, + { + plugin.build(self) } } diff --git a/src/core/core_plugin.rs b/src/core/core_plugin.rs new file mode 100644 index 0000000000..cf2cf26bb1 --- /dev/null +++ b/src/core/core_plugin.rs @@ -0,0 +1,15 @@ +use super::{Time, Window}; +use crate::{app::AppBuilder, plugin::AppPlugin}; + +#[derive(Default)] +pub struct CorePlugin; + +impl AppPlugin for CorePlugin { + fn build(&self, app: AppBuilder) -> AppBuilder { + app.add_resource(Window::default()) + .add_resource(Time::new()) + } + fn name(&self) -> &'static str { + "Core" + } +} diff --git a/src/core/mod.rs b/src/core/mod.rs index 433823a2bb..31512687dc 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,7 +1,9 @@ pub mod bytes; pub mod time; pub mod window; +mod core_plugin; pub use bytes::GetBytes; pub use time::Time; pub use window::Window; +pub use core_plugin::*; diff --git a/src/diagnostic/diagnostic_plugin.rs b/src/diagnostic/diagnostic_plugin.rs new file mode 100644 index 0000000000..6ddd9f33a3 --- /dev/null +++ b/src/diagnostic/diagnostic_plugin.rs @@ -0,0 +1,43 @@ +use super::{ + diagnostics::{frame_time_diagnostic_system, print_diagnostics_system}, + Diagnostics, +}; +use crate::{app::AppBuilder, plugin::AppPlugin}; +use std::time::Duration; + +pub struct DiagnosticsPlugin { + pub print_wait_duration: Duration, + pub print_diagnostics: bool, + pub add_defaults: bool, +} + +impl Default for DiagnosticsPlugin { + fn default() -> Self { + DiagnosticsPlugin { + print_wait_duration: Duration::from_secs_f64(1.0), + print_diagnostics: false, + add_defaults: true, + } + } +} + +impl AppPlugin for DiagnosticsPlugin { + fn build(&self, mut app: AppBuilder) -> AppBuilder { + app = app.add_resource(Diagnostics::default()); + if self.add_defaults { + let frame_time_diagnostic_system = { + frame_time_diagnostic_system(&mut app.resources, 10) + }; + app = app.add_system(frame_time_diagnostic_system) + } + + if self.print_diagnostics { + app = app.add_system(print_diagnostics_system(self.print_wait_duration)); + } + + app + } + fn name(&self) -> &'static str { + "Diagnostics" + } +} diff --git a/src/diagnostic/mod.rs b/src/diagnostic/mod.rs index 766a5d5e63..6cb957da16 100644 --- a/src/diagnostic/mod.rs +++ b/src/diagnostic/mod.rs @@ -1,4 +1,6 @@ pub mod diagnostics; +mod diagnostic_plugin; +pub use diagnostic_plugin::*; use std::{ collections::{HashMap, VecDeque}, diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs index 35b1791e92..8f4bfd7630 100644 --- a/src/plugin/mod.rs +++ b/src/plugin/mod.rs @@ -3,7 +3,7 @@ use libloading::{Library, Symbol}; use std::any::Any; pub trait AppPlugin: Any + Send + Sync { - fn build(&self, app_builder: &mut AppBuilder) -> &mut AppBuilder; + fn build(&self, app: AppBuilder) -> AppBuilder; fn name(&self) -> &'static str; } diff --git a/src/prelude.rs b/src/prelude.rs index 08ac1e49a2..27d67e5d87 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -11,11 +11,13 @@ pub use crate::{ mesh::{Mesh, MeshType}, pipeline::PipelineDescriptor, render_resource::{resource_name, resource_providers::UniformResourceProvider}, + render_graph::RenderGraph, shader::{uniforms::StandardMaterial, Shader, ShaderDefSuffixProvider, ShaderStage}, texture::{Texture, TextureType}, ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Light, Renderable, }, ui::{Anchors, Margins, Node}, + diagnostic::DiagnosticsPlugin, }; pub use bevy_derive::*; pub use bevy_transform::prelude::*; diff --git a/src/render/mod.rs b/src/render/mod.rs index fe5f99315a..4c58d15bca 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -2,6 +2,7 @@ mod camera; pub mod mesh; pub mod render_graph; pub mod shader; +mod render_plugin; mod color; mod light; @@ -11,6 +12,7 @@ pub use camera::*; pub use color::*; pub use light::*; pub use renderable::*; +pub use render_plugin::*; pub use vertex::Vertex; diff --git a/src/render/pass/passes/forward.rs b/src/render/pass/passes/forward.rs index 0b794253b2..9fe665423e 100644 --- a/src/render/pass/passes/forward.rs +++ b/src/render/pass/passes/forward.rs @@ -13,7 +13,7 @@ pub trait ForwardPassBuilder { fn add_forward_pass(&mut self) -> &mut Self; } -impl<'a> ForwardPassBuilder for RenderGraphBuilder<'a> { +impl<'a, 'b, 'c> ForwardPassBuilder for RenderGraphBuilder<'a, 'b, 'c> { fn add_forward_pass(&mut self) -> &mut Self { self.add_resource_provider(FrameTextureResourceProvider::new( resource_name::texture::DEPTH, diff --git a/src/render/pipeline/pipelines/forward/mod.rs b/src/render/pipeline/pipelines/forward/mod.rs index e453f0cef4..4b318f6f82 100644 --- a/src/render/pipeline/pipelines/forward/mod.rs +++ b/src/render/pipeline/pipelines/forward/mod.rs @@ -13,7 +13,7 @@ pub trait ForwardPipelineBuilder { fn add_forward_pipeline(&mut self) -> &mut Self; } -impl<'a> ForwardPipelineBuilder for RenderGraphBuilder<'a> { +impl<'a, 'b, 'c> ForwardPipelineBuilder for RenderGraphBuilder<'a, 'b, 'c> { fn add_forward_pipeline(&mut self) -> &mut Self { self.add_pipeline(resource_name::pipeline::FORWARD, |builder| { builder diff --git a/src/render/pipeline/pipelines/forward_flat/mod.rs b/src/render/pipeline/pipelines/forward_flat/mod.rs index 550528bcfb..917469648b 100644 --- a/src/render/pipeline/pipelines/forward_flat/mod.rs +++ b/src/render/pipeline/pipelines/forward_flat/mod.rs @@ -14,7 +14,7 @@ pub trait ForwardFlatPipelineBuilder { fn add_forward_flat_pipeline(&mut self) -> &mut Self; } -impl<'a> ForwardFlatPipelineBuilder for RenderGraphBuilder<'a> { +impl<'a, 'b, 'c> ForwardFlatPipelineBuilder for RenderGraphBuilder<'a, 'b, 'c> { fn add_forward_flat_pipeline(&mut self) -> &mut Self { self.add_pipeline(resource_name::pipeline::FORWARD_FLAT, |builder| { builder diff --git a/src/render/pipeline/pipelines/ui/mod.rs b/src/render/pipeline/pipelines/ui/mod.rs index 4389347021..082a1156cd 100644 --- a/src/render/pipeline/pipelines/ui/mod.rs +++ b/src/render/pipeline/pipelines/ui/mod.rs @@ -13,7 +13,7 @@ pub trait UiPipelineBuilder { fn add_ui_pipeline(&mut self) -> &mut Self; } -impl<'a> UiPipelineBuilder for RenderGraphBuilder<'a> { +impl<'a, 'b, 'c> UiPipelineBuilder for RenderGraphBuilder<'a, 'b, 'c> { fn add_ui_pipeline(&mut self) -> &mut Self { self.add_pipeline(resource_name::pipeline::UI, |builder| { builder diff --git a/src/render/render_graph/render_graph.rs b/src/render/render_graph/render_graph.rs index 4c2dfe7dc5..c97db8ed7e 100644 --- a/src/render/render_graph/render_graph.rs +++ b/src/render/render_graph/render_graph.rs @@ -1,7 +1,7 @@ use super::RenderGraphBuilder; use crate::{ - asset::Handle, - prelude::Resources, + asset::{AssetStorage, Handle}, + prelude::Shader, render::{ draw_target::DrawTarget, pass::PassDescriptor, @@ -25,11 +25,16 @@ pub struct RenderGraph { } impl RenderGraph { - pub fn build(self, resources: &mut Resources) -> RenderGraphBuilder { + pub fn build<'a, 'b, 'c>( + &'c mut self, + pipelines: &'a mut AssetStorage, + shaders: &'b mut AssetStorage, + ) -> RenderGraphBuilder<'a, 'b, 'c> { RenderGraphBuilder { - resources, + pipelines, + shaders, current_pass: None, - render_graph: Some(self), + render_graph: self, } } diff --git a/src/render/render_graph/render_graph_builder.rs b/src/render/render_graph/render_graph_builder.rs index ce8182f29d..4b3266a5e3 100644 --- a/src/render/render_graph/render_graph_builder.rs +++ b/src/render/render_graph/render_graph_builder.rs @@ -1,7 +1,7 @@ use super::RenderGraph; use crate::{ asset::AssetStorage, - prelude::{Resources, Shader}, + prelude::Shader, render::{ draw_target::DrawTarget, pass::PassDescriptor, @@ -11,18 +11,17 @@ use crate::{ }, }; -pub struct RenderGraphBuilder<'a> { - pub render_graph: Option, - pub resources: &'a mut Resources, +pub struct RenderGraphBuilder<'a, 'b, 'c> { + pub pipelines: &'a mut AssetStorage, + pub shaders: &'b mut AssetStorage, + pub render_graph: &'c mut RenderGraph, pub current_pass: Option, } -impl<'a> RenderGraphBuilder<'a> { +impl<'a, 'b, 'c> RenderGraphBuilder<'a, 'b, 'c> { pub fn add_pass(&mut self, name: &str, pass: PassDescriptor) -> &mut Self { self.current_pass = Some(name.to_string()); self.render_graph - .as_mut() - .unwrap() .pass_descriptors .insert(name.to_string(), pass); self @@ -30,19 +29,12 @@ impl<'a> RenderGraphBuilder<'a> { pub fn add_pipeline(&mut self, name: &str, build: impl Fn(&mut PipelineBuilder)) -> &mut Self { if let Some(ref pass) = self.current_pass { - let mut pipeline_descriptor_storage = self - .resources - .get_mut::>() - .unwrap(); - let mut shader_storage = self.resources.get_mut::>().unwrap(); - let mut builder = PipelineBuilder::new(name, &mut shader_storage); + let mut builder = PipelineBuilder::new(name, &mut self.shaders); build(&mut builder); let pipeline = builder.finish(); - let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline); - pipeline_descriptor_storage.set_name(name, pipeline_descriptor_handle); + let pipeline_descriptor_handle = self.pipelines.add(pipeline); + self.pipelines.set_name(name, pipeline_descriptor_handle); self.render_graph - .as_mut() - .unwrap() .add_pipeline(&pass, pipeline_descriptor_handle); } @@ -56,19 +48,12 @@ impl<'a> RenderGraphBuilder<'a> { build: impl Fn(&mut PipelineBuilder), ) -> &mut Self { { - let mut pipeline_descriptor_storage = self - .resources - .get_mut::>() - .unwrap(); - let mut shader_storage = self.resources.get_mut::>().unwrap(); - let mut builder = PipelineBuilder::new(name, &mut shader_storage); + let mut builder = PipelineBuilder::new(name, &mut self.shaders); build(&mut builder); let pipeline = builder.finish(); - let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline); - pipeline_descriptor_storage.set_name(name, pipeline_descriptor_handle); + let pipeline_descriptor_handle = self.pipelines.add(pipeline); + self.pipelines.set_name(name, pipeline_descriptor_handle); self.render_graph - .as_mut() - .unwrap() .add_pipeline(pass, pipeline_descriptor_handle); } @@ -80,8 +65,6 @@ impl<'a> RenderGraphBuilder<'a> { T: ResourceProvider + Send + Sync + 'static, { self.render_graph - .as_mut() - .unwrap() .resource_providers .push(Box::new(resource_provider)); self @@ -89,8 +72,6 @@ impl<'a> RenderGraphBuilder<'a> { pub fn add_texture(&mut self, name: &str, texture_descriptor: TextureDescriptor) -> &mut Self { self.render_graph - .as_mut() - .unwrap() .queued_textures .push((name.to_string(), texture_descriptor)); self @@ -101,14 +82,8 @@ impl<'a> RenderGraphBuilder<'a> { T: DrawTarget + Send + Sync + 'static, { self.render_graph - .as_mut() - .unwrap() .draw_targets .insert(draw_target.get_name(), Box::new(draw_target)); self } - - pub fn finish(&mut self) -> RenderGraph { - self.render_graph.take().unwrap() - } } diff --git a/src/render/render_plugin.rs b/src/render/render_plugin.rs new file mode 100644 index 0000000000..9f2831224d --- /dev/null +++ b/src/render/render_plugin.rs @@ -0,0 +1,78 @@ +use super::{ + draw_target::draw_targets::{ + AssignedBatchesDrawTarget, AssignedMeshesDrawTarget, MeshesDrawTarget, UiDrawTarget, + }, + pass::passes::ForwardPassBuilder, + pipeline::{pipelines::ForwardPipelineBuilder, PipelineCompiler, ShaderPipelineAssignments}, + render_graph::RenderGraph, + render_resource::{ + resource_providers::{ + Camera2dResourceProvider, CameraResourceProvider, LightResourceProvider, + MeshResourceProvider, UiResourceProvider, + }, + AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments, + }, +}; +use crate::{ + app::AppBuilder, + asset::AssetStorage, + plugin::AppPlugin, + prelude::{ + LocalToWorld, Mesh, PipelineDescriptor, Shader, StandardMaterial, Texture, + UniformResourceProvider, + }, +}; + +#[derive(Default)] +pub struct RenderPlugin; + +impl RenderPlugin { + pub fn setup_render_graph_defaults(app: &mut AppBuilder) { + let mut pipelines = app + .resources + .get_mut::>() + .unwrap(); + let mut shaders = app.resources.get_mut::>().unwrap(); + let mut render_graph = app.resources.get_mut::().unwrap(); + render_graph + .build(&mut pipelines, &mut shaders) + .add_draw_target(MeshesDrawTarget::default()) + .add_draw_target(AssignedBatchesDrawTarget::default()) + .add_draw_target(AssignedMeshesDrawTarget::default()) + .add_draw_target(UiDrawTarget::default()) + .add_resource_provider(CameraResourceProvider::default()) + .add_resource_provider(Camera2dResourceProvider::default()) + .add_resource_provider(LightResourceProvider::new(10)) + .add_resource_provider(UiResourceProvider::new()) + .add_resource_provider(MeshResourceProvider::new()) + .add_resource_provider(UniformResourceProvider::::new(true)) + .add_resource_provider(UniformResourceProvider::::new(true)) + .add_forward_pass() + .add_forward_pipeline(); + } +} + +impl AppPlugin for RenderPlugin { + fn build(&self, mut app: AppBuilder) -> AppBuilder { + let mut asset_batchers = AssetBatchers::default(); + asset_batchers.batch_types2::(); + app = app + .add_resource(RenderGraph::default()) + .add_resource(AssetStorage::::new()) + .add_resource(AssetStorage::::new()) + .add_resource(AssetStorage::::new()) + .add_resource(AssetStorage::::new()) + .add_resource(AssetStorage::::new()) + .add_resource(ShaderPipelineAssignments::new()) + .add_resource(PipelineCompiler::new()) + .add_resource(RenderResourceAssignments::default()) + .add_resource(EntityRenderResourceAssignments::default()) + .add_resource(asset_batchers); + RenderPlugin::setup_render_graph_defaults(&mut app); + app + } + + fn name(&self) -> &'static str { + "Render" + } +} diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs index 990275ed2e..fcae59a804 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_render_pass.rs @@ -1,7 +1,9 @@ use super::{WgpuRenderer, WgpuResources}; use crate::render::{ - pipeline::{BindGroupDescriptorId, PipelineDescriptor}, - render_resource::{RenderResource, RenderResourceAssignments, ResourceInfo, RenderResourceSetId}, + pipeline::PipelineDescriptor, + render_resource::{ + RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo, + }, renderer::{RenderPass, Renderer}, }; use std::{collections::HashMap, ops::Range}; @@ -11,7 +13,7 @@ pub struct WgpuRenderPass<'a, 'b, 'c, 'd> { pub pipeline_descriptor: &'c PipelineDescriptor, pub wgpu_resources: &'a WgpuResources, pub renderer: &'d WgpuRenderer, - pub bound_bind_groups: HashMap, + pub bound_bind_groups: HashMap, } impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { @@ -53,10 +55,19 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { if let Some((vertex_buffer, index_buffer)) = render_resource_assignments.get_vertex_buffer(&vertex_buffer_descriptor.name) { - log::trace!("set vertex buffer {}: {} ({:?})", i, vertex_buffer_descriptor.name, vertex_buffer); + log::trace!( + "set vertex buffer {}: {} ({:?})", + i, + vertex_buffer_descriptor.name, + vertex_buffer + ); self.set_vertex_buffer(i as u32, vertex_buffer, 0); if let Some(index_buffer) = index_buffer { - log::trace!("set index buffer: {} ({:?})", vertex_buffer_descriptor.name, index_buffer); + log::trace!( + "set index buffer: {} ({:?})", + vertex_buffer_descriptor.name, + index_buffer + ); self.set_index_buffer(index_buffer, 0); match self.renderer.get_resource_info(index_buffer).unwrap() { ResourceInfo::Buffer(buffer_info) => { @@ -86,8 +97,11 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { // don't bind bind groups if they are already set // TODO: these checks come at a performance cost. make sure its worth it! - if let Some(bound_render_resource_set) = self.bound_bind_groups.get(&bind_group.index) { - if *bound_render_resource_set == *render_resource_set_id && dynamic_uniform_indices.len() == 0 + if let Some(bound_render_resource_set) = + self.bound_bind_groups.get(&bind_group.index) + { + if *bound_render_resource_set == *render_resource_set_id + && dynamic_uniform_indices.len() == 0 { continue; } @@ -99,8 +113,13 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { } else { self.bound_bind_groups.remove(&bind_group.index); } - - log::trace!("set bind group {} {:?}: {:?}", bind_group.index, dynamic_uniform_indices, render_resource_set_id); + + log::trace!( + "set bind group {} {:?}: {:?}", + bind_group.index, + dynamic_uniform_indices, + render_resource_set_id + ); self.render_pass.set_bind_group( bind_group.index, &wgpu_bind_group,