simplify render graph builder interface
This commit is contained in:
parent
c6d7402318
commit
eaff311a80
@ -10,16 +10,12 @@ struct MyMaterial {
|
||||
fn main() {
|
||||
App::build()
|
||||
.add_defaults()
|
||||
.setup_render_graph(|builder, pipeline_storage, shader_storage| {
|
||||
builder
|
||||
.setup_render_graph(|render_graph_builder| {
|
||||
render_graph_builder
|
||||
.add_resource_provider(UniformResourceProvider::<MyMaterial>::new())
|
||||
.add_pipeline_to_pass(
|
||||
resource_name::pass::MAIN,
|
||||
pipeline_storage,
|
||||
PipelineDescriptor::build(
|
||||
"MyMaterial",
|
||||
shader_storage,
|
||||
Shader::from_glsl(
|
||||
.add_pipeline_to_pass(resource_name::pass::MAIN, "MyMaterial", |builder| {
|
||||
builder
|
||||
.with_vertex_shader(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
r#"
|
||||
#version 450
|
||||
@ -36,11 +32,10 @@ fn main() {
|
||||
gl_Position = ViewProj * v_Position;
|
||||
}
|
||||
"#,
|
||||
),
|
||||
)
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
r#"
|
||||
))
|
||||
.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;
|
||||
@ -55,10 +50,9 @@ fn main() {
|
||||
# endif
|
||||
}
|
||||
"#,
|
||||
))
|
||||
.with_standard_config()
|
||||
.finish(),
|
||||
)
|
||||
))
|
||||
.with_standard_config();
|
||||
});
|
||||
})
|
||||
.setup_world(setup)
|
||||
.run();
|
||||
|
||||
@ -14,7 +14,7 @@ use crate::{
|
||||
|
||||
use bevy_transform::{prelude::LocalToWorld, transform_system_bundle};
|
||||
use pipeline::PipelineDescriptor;
|
||||
use render_graph::RenderGraphBuilder;
|
||||
use render_graph::{RenderGraph, RenderGraphBuilder};
|
||||
use render_resource::{
|
||||
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignmentsProvider,
|
||||
};
|
||||
@ -22,11 +22,11 @@ use shader::Shader;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct AppBuilder {
|
||||
pub world: World,
|
||||
pub resources: Resources,
|
||||
pub universe: Universe,
|
||||
pub world: Option<World>,
|
||||
pub resources: Option<Resources>,
|
||||
pub universe: Option<Universe>,
|
||||
pub renderer: Option<Box<dyn Renderer>>,
|
||||
pub render_graph_builder: RenderGraphBuilder,
|
||||
pub render_graph: Option<RenderGraph>,
|
||||
pub setup_systems: Vec<Box<dyn Schedulable>>,
|
||||
pub system_stages: HashMap<String, Vec<Box<dyn Schedulable>>>,
|
||||
pub runnable_stages: HashMap<String, Vec<Box<dyn Runnable>>>,
|
||||
@ -39,10 +39,10 @@ impl AppBuilder {
|
||||
let world = universe.create_world();
|
||||
let resources = Resources::default();
|
||||
AppBuilder {
|
||||
universe,
|
||||
world,
|
||||
resources,
|
||||
render_graph_builder: RenderGraphBuilder::new(),
|
||||
universe: Some(universe),
|
||||
world: Some(world),
|
||||
resources: Some(resources),
|
||||
render_graph: Some(RenderGraph::default()),
|
||||
renderer: None,
|
||||
setup_systems: Vec::new(),
|
||||
system_stages: HashMap::new(),
|
||||
@ -51,14 +51,17 @@ 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 {
|
||||
setup_schedule_builder = setup_schedule_builder.add_system(setup_system);
|
||||
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(&mut self.world, &mut self.resources);
|
||||
setup_schedule.execute(
|
||||
self.world.as_mut().unwrap(),
|
||||
self.resources.as_mut().unwrap(),
|
||||
);
|
||||
|
||||
let mut schedule_builder = Schedule::builder();
|
||||
for stage_name in self.stage_order.iter() {
|
||||
@ -79,42 +82,51 @@ impl AppBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
let render_graph = self.render_graph_builder.build();
|
||||
self.resources.insert(render_graph);
|
||||
self.resources
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(self.render_graph.take().unwrap());
|
||||
|
||||
App::new(
|
||||
self.universe,
|
||||
self.world,
|
||||
self.universe.take().unwrap(),
|
||||
self.world.take().unwrap(),
|
||||
schedule_builder.build(),
|
||||
self.resources,
|
||||
self.renderer,
|
||||
self.resources.take().unwrap(),
|
||||
self.renderer.take(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn run(self) {
|
||||
pub fn run(&mut self) {
|
||||
self.build().run();
|
||||
}
|
||||
|
||||
pub fn with_world(mut self, world: World) -> Self {
|
||||
self.world = world;
|
||||
pub fn with_world(&mut self, world: World) -> &mut Self {
|
||||
self.world = Some(world);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn setup_world(mut self, setup: impl Fn(&mut World, &mut Resources)) -> Self {
|
||||
setup(&mut self.world, &mut self.resources);
|
||||
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(),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_system(self, system: Box<dyn Schedulable>) -> Self {
|
||||
pub fn add_system(&mut self, system: Box<dyn Schedulable>) -> &mut Self {
|
||||
self.add_system_to_stage(system_stage::UPDATE, system)
|
||||
}
|
||||
|
||||
pub fn add_setup_system(mut self, system: Box<dyn Schedulable>) -> Self {
|
||||
pub fn add_setup_system(&mut self, system: Box<dyn Schedulable>) -> &mut Self {
|
||||
self.setup_systems.push(system);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_system_to_stage(mut self, stage_name: &str, system: Box<dyn Schedulable>) -> Self {
|
||||
pub fn add_system_to_stage(
|
||||
&mut self,
|
||||
stage_name: &str,
|
||||
system: Box<dyn Schedulable>,
|
||||
) -> &mut Self {
|
||||
if let None = self.system_stages.get(stage_name) {
|
||||
self.system_stages
|
||||
.insert(stage_name.to_string(), Vec::new());
|
||||
@ -127,7 +139,11 @@ impl AppBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_runnable_to_stage(mut self, stage_name: &str, system: Box<dyn Runnable>) -> Self {
|
||||
pub fn add_runnable_to_stage(
|
||||
&mut self,
|
||||
stage_name: &str,
|
||||
system: Box<dyn Runnable>,
|
||||
) -> &mut Self {
|
||||
if let None = self.runnable_stages.get(stage_name) {
|
||||
self.runnable_stages
|
||||
.insert(stage_name.to_string(), Vec::new());
|
||||
@ -140,38 +156,37 @@ impl AppBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_default_resources(mut self) -> Self {
|
||||
pub fn add_default_resources(&mut self) -> &mut Self {
|
||||
let mut asset_batchers = AssetBatchers::default();
|
||||
asset_batchers.batch_types2::<Mesh, StandardMaterial>();
|
||||
self.resources.insert(Time::new());
|
||||
self.resources.insert(AssetStorage::<Mesh>::new());
|
||||
self.resources.insert(AssetStorage::<Texture>::new());
|
||||
self.resources.insert(AssetStorage::<Shader>::new());
|
||||
self.resources
|
||||
.insert(AssetStorage::<StandardMaterial>::new());
|
||||
self.resources
|
||||
.insert(AssetStorage::<PipelineDescriptor>::new());
|
||||
self.resources.insert(ShaderPipelineAssignments::new());
|
||||
self.resources.insert(CompiledShaderMap::new());
|
||||
self.resources
|
||||
.insert(RenderResourceAssignmentsProvider::default());
|
||||
self.resources
|
||||
.insert(EntityRenderResourceAssignments::default());
|
||||
self.resources.insert(asset_batchers);
|
||||
let resources = self.resources.as_mut().unwrap();
|
||||
resources.insert(Time::new());
|
||||
resources.insert(AssetStorage::<Mesh>::new());
|
||||
resources.insert(AssetStorage::<Texture>::new());
|
||||
resources.insert(AssetStorage::<Shader>::new());
|
||||
resources.insert(AssetStorage::<StandardMaterial>::new());
|
||||
resources.insert(AssetStorage::<PipelineDescriptor>::new());
|
||||
resources.insert(ShaderPipelineAssignments::new());
|
||||
resources.insert(CompiledShaderMap::new());
|
||||
resources.insert(RenderResourceAssignmentsProvider::default());
|
||||
resources.insert(EntityRenderResourceAssignments::default());
|
||||
resources.insert(asset_batchers);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_default_systems(mut self) -> Self {
|
||||
self = self.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);
|
||||
pub fn add_default_systems(&mut self) -> &mut Self {
|
||||
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(self) -> Self {
|
||||
self.setup_render_graph(|builder, pipeline_storage, shader_storage| {
|
||||
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())
|
||||
@ -185,37 +200,31 @@ impl AppBuilder {
|
||||
.add_resource_provider(UniformResourceProvider::<StandardMaterial>::new())
|
||||
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new())
|
||||
.add_forward_pass()
|
||||
.add_forward_pipeline(pipeline_storage, shader_storage)
|
||||
.add_ui_pipeline(pipeline_storage, shader_storage)
|
||||
.add_forward_pipeline()
|
||||
.add_ui_pipeline();
|
||||
})
|
||||
}
|
||||
|
||||
pub fn setup_render_graph(
|
||||
mut self,
|
||||
setup: impl Fn(
|
||||
RenderGraphBuilder,
|
||||
&mut AssetStorage<PipelineDescriptor>,
|
||||
&mut AssetStorage<Shader>,
|
||||
) -> RenderGraphBuilder,
|
||||
) -> Self {
|
||||
pub fn setup_render_graph<'a>(
|
||||
&'a mut self,
|
||||
setup: impl Fn(&'_ mut RenderGraphBuilder<'_>),
|
||||
) -> &'a mut Self {
|
||||
{
|
||||
let mut pipeline_storage = self
|
||||
.resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut shader_storage = self.resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
self.render_graph_builder = setup(
|
||||
self.render_graph_builder,
|
||||
&mut pipeline_storage,
|
||||
&mut shader_storage,
|
||||
);
|
||||
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());
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "wgpu")]
|
||||
pub fn add_wgpu_renderer(mut self) -> Self {
|
||||
pub fn add_wgpu_renderer(&mut self) -> &mut Self {
|
||||
self.renderer = Some(Box::new(
|
||||
renderer::renderers::wgpu_renderer::WgpuRenderer::new(),
|
||||
));
|
||||
@ -223,20 +232,20 @@ impl AppBuilder {
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "wgpu"))]
|
||||
fn add_wgpu_renderer(self) -> Self {
|
||||
fn add_wgpu_renderer(&mut self) -> &mut Self {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_defaults(self) -> Self {
|
||||
pub fn add_defaults(&mut self) -> &mut Self {
|
||||
self.add_default_resources()
|
||||
.add_default_systems()
|
||||
.add_render_graph_defaults()
|
||||
.add_wgpu_renderer()
|
||||
}
|
||||
|
||||
pub fn load_plugin(mut self, path: &str) -> Self {
|
||||
pub fn load_plugin(&mut self, path: &str) -> &mut Self {
|
||||
let (_lib, plugin) = load_plugin(path);
|
||||
self = plugin.build(self);
|
||||
plugin.build(self);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use libloading::{Library, Symbol};
|
||||
use std::any::Any;
|
||||
|
||||
pub trait AppPlugin: Any + Send + Sync {
|
||||
fn build(&self, app_builder: AppBuilder) -> AppBuilder;
|
||||
fn build(&self, app_builder: &mut AppBuilder) -> &mut AppBuilder;
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
|
||||
@ -10,11 +10,11 @@ use crate::render::{
|
||||
};
|
||||
|
||||
pub trait ForwardPassBuilder {
|
||||
fn add_forward_pass(self) -> Self;
|
||||
fn add_forward_pass(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ForwardPassBuilder for RenderGraphBuilder {
|
||||
fn add_forward_pass(self) -> Self {
|
||||
impl<'a> ForwardPassBuilder for RenderGraphBuilder<'a> {
|
||||
fn add_forward_pass(&mut self) -> &mut Self {
|
||||
self.add_resource_provider(FrameTextureResourceProvider::new(
|
||||
resource_name::texture::DEPTH,
|
||||
TextureDescriptor {
|
||||
|
||||
@ -108,64 +108,69 @@ impl PipelineDescriptor {
|
||||
|
||||
impl PipelineDescriptor {
|
||||
pub fn build<'a>(
|
||||
name: &str,
|
||||
name: &'a str,
|
||||
shader_storage: &'a mut AssetStorage<Shader>,
|
||||
vertex_shader: Shader,
|
||||
) -> PipelineBuilder<'a> {
|
||||
PipelineBuilder::new(name, shader_storage, vertex_shader)
|
||||
PipelineBuilder::new(name, shader_storage)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PipelineBuilder<'a> {
|
||||
pipeline: PipelineDescriptor,
|
||||
pipeline: Option<PipelineDescriptor>,
|
||||
shader_storage: &'a mut AssetStorage<Shader>,
|
||||
name: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> PipelineBuilder<'a> {
|
||||
pub fn new(
|
||||
name: &str,
|
||||
name: &'a str,
|
||||
shader_storage: &'a mut AssetStorage<Shader>,
|
||||
vertex_shader: Shader,
|
||||
) -> Self {
|
||||
let vertex_shader_handle = shader_storage.add(vertex_shader);
|
||||
PipelineBuilder {
|
||||
pipeline: PipelineDescriptor::new(Some(name), vertex_shader_handle),
|
||||
pipeline: None,
|
||||
shader_storage,
|
||||
name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(self) -> PipelineDescriptor {
|
||||
self.pipeline
|
||||
pub fn finish(&mut self) -> PipelineDescriptor {
|
||||
self.pipeline.take().unwrap()
|
||||
}
|
||||
|
||||
pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self {
|
||||
let fragment_shader_handle = self.shader_storage.add(fragment_shader);
|
||||
self.pipeline.shader_stages.fragment = Some(fragment_shader_handle);
|
||||
pub fn with_vertex_shader(&mut self, vertex_shader: Shader) -> &mut Self {
|
||||
let vertex_shader_handle = self.shader_storage.add(vertex_shader);
|
||||
self.pipeline = Some(PipelineDescriptor::new(Some(&self.name), vertex_shader_handle));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_color_state(mut self, color_state_descriptor: ColorStateDescriptor) -> Self {
|
||||
self.pipeline.color_states.push(color_state_descriptor);
|
||||
pub fn with_fragment_shader(&mut self, fragment_shader: Shader) -> &mut Self {
|
||||
let fragment_shader_handle = self.shader_storage.add(fragment_shader);
|
||||
self.pipeline.as_mut().unwrap().shader_stages.fragment = Some(fragment_shader_handle);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_color_state(&mut self, color_state_descriptor: ColorStateDescriptor) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().color_states.push(color_state_descriptor);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_depth_stencil_state(
|
||||
mut self,
|
||||
&mut self,
|
||||
depth_stencil_state: DepthStencilStateDescriptor,
|
||||
) -> Self {
|
||||
if let Some(_) = self.pipeline.depth_stencil_state {
|
||||
) -> &mut Self {
|
||||
if let Some(_) = self.pipeline.as_ref().unwrap().depth_stencil_state {
|
||||
panic!("Depth stencil state has already been set");
|
||||
}
|
||||
self.pipeline.depth_stencil_state = Some(depth_stencil_state);
|
||||
self.pipeline.as_mut().unwrap().depth_stencil_state = Some(depth_stencil_state);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_bind_group(mut self, bind_group: BindGroup) -> Self {
|
||||
if let PipelineLayoutType::Reflected(_) = self.pipeline.layout {
|
||||
self.pipeline.layout = PipelineLayoutType::Manual(PipelineLayout::new());
|
||||
pub fn add_bind_group(&mut self, bind_group: BindGroup) -> &mut Self {
|
||||
if let PipelineLayoutType::Reflected(_) = self.pipeline.as_ref().unwrap().layout {
|
||||
self.pipeline.as_mut().unwrap().layout = PipelineLayoutType::Manual(PipelineLayout::new());
|
||||
}
|
||||
|
||||
if let PipelineLayoutType::Manual(ref mut layout) = self.pipeline.layout {
|
||||
if let PipelineLayoutType::Manual(ref mut layout) = self.pipeline.as_mut().unwrap().layout {
|
||||
layout.bind_groups.push(bind_group);
|
||||
}
|
||||
|
||||
@ -173,55 +178,55 @@ impl<'a> PipelineBuilder<'a> {
|
||||
}
|
||||
|
||||
pub fn add_vertex_buffer_descriptor(
|
||||
mut self,
|
||||
&mut self,
|
||||
vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||
) -> Self {
|
||||
self.pipeline.reflect_vertex_buffer_descriptors = false;
|
||||
self.pipeline
|
||||
) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().reflect_vertex_buffer_descriptors = false;
|
||||
self.pipeline.as_mut().unwrap()
|
||||
.vertex_buffer_descriptors
|
||||
.push(vertex_buffer_descriptor);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_index_format(mut self, index_format: IndexFormat) -> Self {
|
||||
self.pipeline.index_format = index_format;
|
||||
pub fn with_index_format(&mut self, index_format: IndexFormat) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().index_format = index_format;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_draw_target(mut self, name: &str) -> Self {
|
||||
self.pipeline.draw_targets.push(name.to_string());
|
||||
pub fn add_draw_target(&mut self, name: &str) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().draw_targets.push(name.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_rasterization_state(
|
||||
mut self,
|
||||
&mut self,
|
||||
rasterization_state: RasterizationStateDescriptor,
|
||||
) -> Self {
|
||||
self.pipeline.rasterization_state = Some(rasterization_state);
|
||||
) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().rasterization_state = Some(rasterization_state);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_primitive_topology(mut self, primitive_topology: PrimitiveTopology) -> Self {
|
||||
self.pipeline.primitive_topology = primitive_topology;
|
||||
pub fn with_primitive_topology(&mut self, primitive_topology: PrimitiveTopology) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().primitive_topology = primitive_topology;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_sample_count(mut self, sample_count: u32) -> Self {
|
||||
self.pipeline.sample_count = sample_count;
|
||||
pub fn with_sample_count(&mut self, sample_count: u32) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().sample_count = sample_count;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_alpha_to_coverage_enabled(mut self, alpha_to_coverage_enabled: bool) -> Self {
|
||||
self.pipeline.alpha_to_coverage_enabled = alpha_to_coverage_enabled;
|
||||
pub fn with_alpha_to_coverage_enabled(&mut self, alpha_to_coverage_enabled: bool) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().alpha_to_coverage_enabled = alpha_to_coverage_enabled;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_sample_mask(mut self, sample_mask: u32) -> Self {
|
||||
self.pipeline.sample_mask = sample_mask;
|
||||
pub fn with_sample_mask(&mut self, sample_mask: u32) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().sample_mask = sample_mask;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_standard_config(self) -> Self {
|
||||
pub fn with_standard_config(&mut self) -> &mut Self {
|
||||
self.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
|
||||
@ -1,78 +1,62 @@
|
||||
use crate::{
|
||||
asset::AssetStorage,
|
||||
render::{
|
||||
pipeline::{
|
||||
state_descriptors::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace,
|
||||
RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
},
|
||||
PipelineDescriptor,
|
||||
},
|
||||
render_graph::RenderGraphBuilder,
|
||||
render_resource::resource_name,
|
||||
shader::{Shader, ShaderStage},
|
||||
texture::TextureFormat,
|
||||
use crate::render::{
|
||||
pipeline::state_descriptors::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace,
|
||||
RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
},
|
||||
render_graph::RenderGraphBuilder,
|
||||
render_resource::resource_name,
|
||||
shader::{Shader, ShaderStage},
|
||||
texture::TextureFormat,
|
||||
};
|
||||
pub trait ForwardPipelineBuilder {
|
||||
fn add_forward_pipeline(
|
||||
self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
) -> Self;
|
||||
fn add_forward_pipeline(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ForwardPipelineBuilder for RenderGraphBuilder {
|
||||
fn add_forward_pipeline(
|
||||
self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
) -> Self {
|
||||
self.add_pipeline(
|
||||
pipeline_descriptor_storage,
|
||||
PipelineDescriptor::build(
|
||||
resource_name::pipeline::FORWARD,
|
||||
shader_storage,
|
||||
Shader::from_glsl(ShaderStage::Vertex, include_str!("forward.vert")),
|
||||
)
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("forward.frag"),
|
||||
))
|
||||
.with_rasterization_state(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
})
|
||||
.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_BATCHES)
|
||||
.finish(),
|
||||
)
|
||||
impl<'a> ForwardPipelineBuilder for RenderGraphBuilder<'a> {
|
||||
fn add_forward_pipeline(&mut self) -> &mut Self {
|
||||
self.add_pipeline(resource_name::pipeline::FORWARD, |builder| {
|
||||
builder
|
||||
.with_vertex_shader(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
include_str!("forward.vert"),
|
||||
))
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("forward.frag"),
|
||||
))
|
||||
.with_rasterization_state(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
})
|
||||
.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_BATCHES);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use crate::{
|
||||
asset::AssetStorage,
|
||||
render::{
|
||||
pipeline::{
|
||||
state_descriptors::{
|
||||
@ -7,7 +6,6 @@ use crate::{
|
||||
DepthStencilStateDescriptor, FrontFace, RasterizationStateDescriptor,
|
||||
StencilStateFaceDescriptor,
|
||||
},
|
||||
PipelineDescriptor,
|
||||
},
|
||||
render_graph::RenderGraphBuilder,
|
||||
render_resource::resource_name,
|
||||
@ -17,54 +15,44 @@ use crate::{
|
||||
};
|
||||
|
||||
pub trait ForwardFlatPipelineBuilder {
|
||||
fn add_forward_flat_pipeline(
|
||||
self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
) -> Self;
|
||||
fn add_forward_flat_pipeline(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ForwardFlatPipelineBuilder for RenderGraphBuilder {
|
||||
fn add_forward_flat_pipeline(
|
||||
self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
) -> Self {
|
||||
self.add_pipeline(
|
||||
pipeline_descriptor_storage,
|
||||
PipelineDescriptor::build(
|
||||
resource_name::pipeline::FORWARD_FLAT,
|
||||
shader_storage,
|
||||
Shader::from_glsl(ShaderStage::Vertex, include_str!("forward_flat.vert")),
|
||||
)
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("forward_flat.frag"),
|
||||
))
|
||||
.with_rasterization_state(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
})
|
||||
.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor::REPLACE,
|
||||
alpha_blend: BlendDescriptor::REPLACE,
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::MESHES)
|
||||
.finish(),
|
||||
)
|
||||
impl<'a> ForwardFlatPipelineBuilder for RenderGraphBuilder<'a> {
|
||||
fn add_forward_flat_pipeline(&mut self) -> &mut Self {
|
||||
self.add_pipeline(resource_name::pipeline::FORWARD_FLAT, |builder| {
|
||||
builder
|
||||
.with_vertex_shader(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
include_str!("forward_flat.vert"),
|
||||
))
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("forward_flat.frag"),
|
||||
))
|
||||
.with_rasterization_state(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
})
|
||||
.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor::REPLACE,
|
||||
alpha_blend: BlendDescriptor::REPLACE,
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::MESHES);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,77 +1,61 @@
|
||||
use crate::{
|
||||
asset::AssetStorage,
|
||||
render::{
|
||||
pipeline::{
|
||||
state_descriptors::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace,
|
||||
RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
},
|
||||
PipelineDescriptor,
|
||||
},
|
||||
render_graph::RenderGraphBuilder,
|
||||
render_resource::resource_name,
|
||||
shader::{Shader, ShaderStage},
|
||||
texture::TextureFormat,
|
||||
use crate::render::{
|
||||
pipeline::state_descriptors::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace,
|
||||
RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
},
|
||||
render_graph::RenderGraphBuilder,
|
||||
render_resource::resource_name,
|
||||
shader::{Shader, ShaderStage},
|
||||
texture::TextureFormat,
|
||||
};
|
||||
pub trait UiPipelineBuilder {
|
||||
fn add_ui_pipeline(
|
||||
self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
) -> Self;
|
||||
fn add_ui_pipeline(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl UiPipelineBuilder for RenderGraphBuilder {
|
||||
fn add_ui_pipeline(
|
||||
self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
) -> Self {
|
||||
self.add_pipeline(
|
||||
pipeline_descriptor_storage,
|
||||
PipelineDescriptor::build(
|
||||
resource_name::pipeline::UI,
|
||||
shader_storage,
|
||||
Shader::from_glsl(ShaderStage::Vertex, include_str!("ui.vert")),
|
||||
)
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("ui.frag"),
|
||||
))
|
||||
.with_rasterization_state(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::None,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
})
|
||||
.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: false,
|
||||
depth_compare: CompareFunction::Always,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::UI)
|
||||
.finish(),
|
||||
)
|
||||
impl<'a> UiPipelineBuilder for RenderGraphBuilder<'a> {
|
||||
fn add_ui_pipeline(&mut self) -> &mut Self {
|
||||
self.add_pipeline(resource_name::pipeline::UI, |builder| {
|
||||
builder
|
||||
.with_vertex_shader(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
include_str!("ui.vert"),
|
||||
))
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("ui.frag"),
|
||||
))
|
||||
.with_rasterization_state(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::None,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
})
|
||||
.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: false,
|
||||
depth_compare: CompareFunction::Always,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::UI);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
asset::Handle,
|
||||
prelude::Resources,
|
||||
render::{
|
||||
draw_target::DrawTarget,
|
||||
pass::PassDescriptor,
|
||||
@ -9,6 +10,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use super::RenderGraphBuilder;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderGraph {
|
||||
@ -23,6 +25,14 @@ pub struct RenderGraph {
|
||||
}
|
||||
|
||||
impl RenderGraph {
|
||||
pub fn build(self, resources: &mut Resources) -> RenderGraphBuilder {
|
||||
RenderGraphBuilder {
|
||||
resources,
|
||||
current_pass: None,
|
||||
render_graph: Some(self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_pipeline(&mut self, pass: &str, pipeline: Handle<PipelineDescriptor>) {
|
||||
self.pipeline_descriptors.insert(pipeline.clone());
|
||||
|
||||
|
||||
@ -2,43 +2,41 @@ use super::RenderGraph;
|
||||
use crate::{
|
||||
asset::AssetStorage,
|
||||
render::{
|
||||
draw_target::DrawTarget, pass::PassDescriptor, pipeline::PipelineDescriptor,
|
||||
draw_target::DrawTarget, pass::PassDescriptor, pipeline::{PipelineBuilder, PipelineDescriptor},
|
||||
render_resource::ResourceProvider, texture::TextureDescriptor,
|
||||
},
|
||||
}, prelude::{Shader, Resources},
|
||||
};
|
||||
|
||||
pub struct RenderGraphBuilder {
|
||||
render_graph: RenderGraph,
|
||||
current_pass: Option<String>,
|
||||
pub struct RenderGraphBuilder<'a> {
|
||||
pub render_graph: Option<RenderGraph>,
|
||||
pub resources: &'a mut Resources,
|
||||
pub current_pass: Option<String>,
|
||||
}
|
||||
|
||||
impl RenderGraphBuilder {
|
||||
pub fn new() -> Self {
|
||||
RenderGraphBuilder {
|
||||
render_graph: RenderGraph::default(),
|
||||
current_pass: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_pass(mut self, name: &str, pass: PassDescriptor) -> Self {
|
||||
impl<'a> RenderGraphBuilder<'a> {
|
||||
pub fn add_pass(&mut self, name: &str, pass: PassDescriptor) -> &mut Self {
|
||||
self.current_pass = Some(name.to_string());
|
||||
self.render_graph
|
||||
self.render_graph.as_mut().unwrap()
|
||||
.pass_descriptors
|
||||
.insert(name.to_string(), pass);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_pipeline(
|
||||
mut self,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
pipeline: PipelineDescriptor,
|
||||
) -> Self {
|
||||
&mut self,
|
||||
name: &str,
|
||||
build: impl Fn(&mut PipelineBuilder),
|
||||
) -> &mut Self {
|
||||
let mut pipeline_descriptor_storage = self.resources.get_mut::<AssetStorage<PipelineDescriptor>>().unwrap();
|
||||
let mut shader_storage = self.resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
if let Some(ref pass) = self.current_pass {
|
||||
let name = pipeline.name.clone();
|
||||
let mut builder = PipelineBuilder::new(name, &mut shader_storage);
|
||||
build(&mut builder);
|
||||
let pipeline = builder.finish();
|
||||
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
|
||||
pipeline_descriptor_storage
|
||||
.set_name(name.unwrap().as_str(), pipeline_descriptor_handle);
|
||||
self.render_graph
|
||||
.set_name(name, pipeline_descriptor_handle);
|
||||
self.render_graph.as_mut().unwrap()
|
||||
.add_pipeline(&pass, pipeline_descriptor_handle);
|
||||
}
|
||||
|
||||
@ -46,48 +44,52 @@ impl RenderGraphBuilder {
|
||||
}
|
||||
|
||||
pub fn add_pipeline_to_pass(
|
||||
mut self,
|
||||
&mut self,
|
||||
pass: &str,
|
||||
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
pipeline: PipelineDescriptor,
|
||||
) -> Self {
|
||||
let name = pipeline.name.clone();
|
||||
name: &str,
|
||||
build: impl Fn(&mut PipelineBuilder),
|
||||
) -> &mut Self {
|
||||
let mut pipeline_descriptor_storage = self.resources.get_mut::<AssetStorage<PipelineDescriptor>>().unwrap();
|
||||
let mut shader_storage = self.resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
let mut builder = PipelineBuilder::new(name, &mut shader_storage);
|
||||
build(&mut builder);
|
||||
let pipeline = builder.finish();
|
||||
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
|
||||
pipeline_descriptor_storage.set_name(name.unwrap().as_str(), pipeline_descriptor_handle);
|
||||
self.render_graph
|
||||
pipeline_descriptor_storage.set_name(name, pipeline_descriptor_handle);
|
||||
self.render_graph.as_mut().unwrap()
|
||||
.add_pipeline(pass, pipeline_descriptor_handle);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_resource_provider<T>(mut self, resource_provider: T) -> Self
|
||||
pub fn add_resource_provider<T>(&mut self, resource_provider: T) -> &mut Self
|
||||
where
|
||||
T: ResourceProvider + Send + Sync + 'static,
|
||||
{
|
||||
self.render_graph
|
||||
self.render_graph.as_mut().unwrap()
|
||||
.resource_providers
|
||||
.push(Box::new(resource_provider));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_texture(mut self, name: &str, texture_descriptor: TextureDescriptor) -> Self {
|
||||
self.render_graph
|
||||
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
|
||||
}
|
||||
|
||||
pub fn add_draw_target<T>(mut self, draw_target: T) -> Self
|
||||
pub fn add_draw_target<T>(&mut self, draw_target: T) -> &mut Self
|
||||
where
|
||||
T: DrawTarget + Send + Sync + 'static,
|
||||
{
|
||||
self.render_graph
|
||||
self.render_graph.as_mut().unwrap()
|
||||
.draw_targets
|
||||
.insert(draw_target.get_name(), Box::new(draw_target));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> RenderGraph {
|
||||
self.render_graph
|
||||
pub fn finish(&mut self) -> RenderGraph {
|
||||
self.render_graph.take().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user