remove DrawTargets in favor of PassNodes and in preparation for "immediate mode" drawing api
This commit is contained in:
		
							parent
							
								
									6531ccddab
								
							
						
					
					
						commit
						1426208e2f
					
				@ -2,7 +2,6 @@ use crate::{material::StandardMaterial, nodes::LightsNode, pipelines::build_forw
 | 
			
		||||
use bevy_asset::Assets;
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    base_render_graph,
 | 
			
		||||
    draw_target::AssignedMeshesDrawTarget,
 | 
			
		||||
    pipeline::PipelineDescriptor,
 | 
			
		||||
    render_graph::{
 | 
			
		||||
        nodes::{AssetUniformNode, PassNode, UniformNode},
 | 
			
		||||
@ -41,10 +40,7 @@ impl ForwardPbrRenderGraphBuilder for RenderGraph {
 | 
			
		||||
            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)],
 | 
			
		||||
            );
 | 
			
		||||
            main_pass.add_pipeline(pipelines.add_default(build_forward_pipeline(&mut shaders)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: replace these with "autowire" groups
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								crates/bevy_render/src/draw.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								crates/bevy_render/src/draw.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
use crate::{render_resource::RenderResourceId, pipeline::PipelineDescriptor};
 | 
			
		||||
use bevy_asset::Handle;
 | 
			
		||||
use std::ops::Range;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Eq, PartialEq)]
 | 
			
		||||
pub enum DrawType {
 | 
			
		||||
    Instanced {
 | 
			
		||||
        indices: Range<u32>,
 | 
			
		||||
        base_vertex: i32,
 | 
			
		||||
        instances: Range<u32>,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Eq, PartialEq)]
 | 
			
		||||
pub struct VertexBufferBinding {
 | 
			
		||||
    pub slot: u32,
 | 
			
		||||
    pub vertex_buffer: RenderResourceId,
 | 
			
		||||
    pub offset: u64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Eq, PartialEq)]
 | 
			
		||||
pub struct IndexBufferBinding {
 | 
			
		||||
    pub vertex_buffer: RenderResourceId,
 | 
			
		||||
    pub offset: u64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Eq, PartialEq)]
 | 
			
		||||
pub struct BindGroupBinding {
 | 
			
		||||
    pub vertex_buffer: RenderResourceId,
 | 
			
		||||
    pub offset: u64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Eq, PartialEq)]
 | 
			
		||||
pub struct DrawCall {
 | 
			
		||||
    pub pipeline: Handle<PipelineDescriptor>,
 | 
			
		||||
    pub draw_type: DrawType,
 | 
			
		||||
    pub vertex_buffers: Vec<VertexBufferBinding>,
 | 
			
		||||
    pub index_buffer: Option<IndexBufferBinding>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Draw {}
 | 
			
		||||
@ -1,25 +0,0 @@
 | 
			
		||||
use crate::{pass::RenderPass, pipeline::PipelineDescriptor, renderer::RenderContext};
 | 
			
		||||
use bevy_asset::Handle;
 | 
			
		||||
use legion::prelude::{Resources, World};
 | 
			
		||||
 | 
			
		||||
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
 | 
			
		||||
pub trait DrawTarget: Send + Sync + 'static {
 | 
			
		||||
    fn draw(
 | 
			
		||||
        &self,
 | 
			
		||||
        world: &World,
 | 
			
		||||
        resources: &Resources,
 | 
			
		||||
        render_pass: &mut dyn RenderPass,
 | 
			
		||||
        pipeline_handle: Handle<PipelineDescriptor>,
 | 
			
		||||
        pipeline_descriptor: &PipelineDescriptor,
 | 
			
		||||
    );
 | 
			
		||||
    fn setup(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        _world: &World,
 | 
			
		||||
        _resources: &Resources,
 | 
			
		||||
        _render_context: &mut dyn RenderContext,
 | 
			
		||||
        _pipeline_handle: Handle<PipelineDescriptor>,
 | 
			
		||||
        _pipeline_descriptor: &PipelineDescriptor,
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
    fn get_name(&self) -> String;
 | 
			
		||||
}
 | 
			
		||||
@ -1,106 +0,0 @@
 | 
			
		||||
use bevy_asset::Handle;
 | 
			
		||||
use legion::prelude::*;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    draw_target::DrawTarget,
 | 
			
		||||
    pass::RenderPass,
 | 
			
		||||
    pipeline::{PipelineAssignments, PipelineDescriptor},
 | 
			
		||||
    render_resource::{
 | 
			
		||||
        EntitiesWaitingForAssets, EntityRenderResourceAssignments, RenderResourceAssignments,
 | 
			
		||||
    },
 | 
			
		||||
    renderer::RenderContext,
 | 
			
		||||
    Renderable,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
pub struct AssignedMeshesDrawTarget;
 | 
			
		||||
 | 
			
		||||
impl AssignedMeshesDrawTarget {
 | 
			
		||||
    pub const NAME: &'static str = "AssignedMeshes";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DrawTarget for AssignedMeshesDrawTarget {
 | 
			
		||||
    fn draw(
 | 
			
		||||
        &self,
 | 
			
		||||
        world: &World,
 | 
			
		||||
        resources: &Resources,
 | 
			
		||||
        render_pass: &mut dyn RenderPass,
 | 
			
		||||
        pipeline_handle: Handle<PipelineDescriptor>,
 | 
			
		||||
        pipeline_descriptor: &PipelineDescriptor,
 | 
			
		||||
    ) {
 | 
			
		||||
        let shader_pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
 | 
			
		||||
        let entity_render_resource_assignments =
 | 
			
		||||
            resources.get::<EntityRenderResourceAssignments>().unwrap();
 | 
			
		||||
        let entities_waiting_for_assets = resources.get::<EntitiesWaitingForAssets>().unwrap();
 | 
			
		||||
        let global_render_resource_assignments =
 | 
			
		||||
            resources.get::<RenderResourceAssignments>().unwrap();
 | 
			
		||||
        render_pass.set_render_resources(pipeline_descriptor, &global_render_resource_assignments);
 | 
			
		||||
 | 
			
		||||
        let assigned_render_resource_assignments = shader_pipeline_assignments
 | 
			
		||||
            .assignments
 | 
			
		||||
            .get(&pipeline_handle);
 | 
			
		||||
 | 
			
		||||
        if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments {
 | 
			
		||||
            for assignment_id in assigned_render_resource_assignments.iter() {
 | 
			
		||||
                // TODO: hopefully legion has better random access apis that are more like queries?
 | 
			
		||||
                let entity = entity_render_resource_assignments
 | 
			
		||||
                    .get(*assignment_id)
 | 
			
		||||
                    .unwrap();
 | 
			
		||||
                let renderable = world.get_component::<Renderable>(*entity).unwrap();
 | 
			
		||||
                if !renderable.is_visible
 | 
			
		||||
                    || renderable.is_instanced
 | 
			
		||||
                    || entities_waiting_for_assets.contains(entity)
 | 
			
		||||
                {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if let Some(indices) = render_pass.set_render_resources(
 | 
			
		||||
                    pipeline_descriptor,
 | 
			
		||||
                    &renderable.render_resource_assignments,
 | 
			
		||||
                ) {
 | 
			
		||||
                    render_pass.draw_indexed(indices, 0, 0..1);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn setup(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        world: &World,
 | 
			
		||||
        resources: &Resources,
 | 
			
		||||
        render_context: &mut dyn RenderContext,
 | 
			
		||||
        pipeline_handle: Handle<PipelineDescriptor>,
 | 
			
		||||
        pipeline_descriptor: &PipelineDescriptor,
 | 
			
		||||
    ) {
 | 
			
		||||
        let pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
 | 
			
		||||
        let entity_render_resource_assignments =
 | 
			
		||||
            resources.get::<EntityRenderResourceAssignments>().unwrap();
 | 
			
		||||
        let assigned_render_resource_assignments =
 | 
			
		||||
            pipeline_assignments.assignments.get(&pipeline_handle);
 | 
			
		||||
        let global_render_resource_assignments =
 | 
			
		||||
            resources.get::<RenderResourceAssignments>().unwrap();
 | 
			
		||||
        render_context
 | 
			
		||||
            .resources()
 | 
			
		||||
            .setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments);
 | 
			
		||||
        if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments {
 | 
			
		||||
            for assignment_id in assigned_render_resource_assignments.iter() {
 | 
			
		||||
                let entity = entity_render_resource_assignments
 | 
			
		||||
                    .get(*assignment_id)
 | 
			
		||||
                    .unwrap();
 | 
			
		||||
                let renderable = world.get_component::<Renderable>(*entity).unwrap();
 | 
			
		||||
                if !renderable.is_visible || renderable.is_instanced {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                render_context.resources().setup_bind_groups(
 | 
			
		||||
                    pipeline_descriptor,
 | 
			
		||||
                    &renderable.render_resource_assignments,
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_name(&self) -> String {
 | 
			
		||||
        AssignedMeshesDrawTarget::NAME.to_string()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,71 +0,0 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    draw_target::DrawTarget,
 | 
			
		||||
    mesh::{self, Mesh},
 | 
			
		||||
    pass::RenderPass,
 | 
			
		||||
    pipeline::PipelineDescriptor,
 | 
			
		||||
    render_resource::ResourceInfo,
 | 
			
		||||
    Renderable,
 | 
			
		||||
};
 | 
			
		||||
use bevy_asset::Handle;
 | 
			
		||||
use legion::prelude::*;
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
pub struct MeshesDrawTarget;
 | 
			
		||||
 | 
			
		||||
impl MeshesDrawTarget {
 | 
			
		||||
    pub const NAME: &'static str = "Meshes";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DrawTarget for MeshesDrawTarget {
 | 
			
		||||
    fn draw(
 | 
			
		||||
        &self,
 | 
			
		||||
        world: &World,
 | 
			
		||||
        _resources: &Resources,
 | 
			
		||||
        render_pass: &mut dyn RenderPass,
 | 
			
		||||
        _pipeline_handle: Handle<PipelineDescriptor>,
 | 
			
		||||
        pipeline_descriptor: &PipelineDescriptor,
 | 
			
		||||
    ) {
 | 
			
		||||
        let mut current_mesh_handle = None;
 | 
			
		||||
        let mut current_mesh_index_len = 0;
 | 
			
		||||
        let mesh_query = <(Read<Handle<Mesh>>, Read<Renderable>)>::query();
 | 
			
		||||
        for (mesh_handle, renderable) in mesh_query.iter(world) {
 | 
			
		||||
            if !renderable.is_visible || renderable.is_instanced {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let render_context = render_pass.get_render_context();
 | 
			
		||||
            let render_resources = render_context.resources();
 | 
			
		||||
            if current_mesh_handle != Some(*mesh_handle) {
 | 
			
		||||
                if let Some(vertex_buffer_resource) = render_resources
 | 
			
		||||
                    .get_asset_resource(*mesh_handle, mesh::VERTEX_BUFFER_ASSET_INDEX)
 | 
			
		||||
                {
 | 
			
		||||
                    let index_buffer_resource = render_resources
 | 
			
		||||
                        .get_asset_resource(*mesh_handle, mesh::INDEX_BUFFER_ASSET_INDEX)
 | 
			
		||||
                        .unwrap();
 | 
			
		||||
                    render_resources.get_resource_info(
 | 
			
		||||
                        index_buffer_resource,
 | 
			
		||||
                        &mut |resource_info| match resource_info {
 | 
			
		||||
                            Some(ResourceInfo::Buffer(Some(buffer_info))) => {
 | 
			
		||||
                                current_mesh_index_len = (buffer_info.size / 2) as u32
 | 
			
		||||
                            }
 | 
			
		||||
                            _ => panic!("expected a buffer type"),
 | 
			
		||||
                        },
 | 
			
		||||
                    );
 | 
			
		||||
                    render_pass.set_index_buffer(index_buffer_resource, 0);
 | 
			
		||||
                    render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0);
 | 
			
		||||
                }
 | 
			
		||||
                // TODO: Verify buffer format matches render pass
 | 
			
		||||
                current_mesh_handle = Some(*mesh_handle);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // TODO: validate bind group properties against shader uniform properties at least once
 | 
			
		||||
            render_pass
 | 
			
		||||
                .set_render_resources(pipeline_descriptor, &renderable.render_resource_assignments);
 | 
			
		||||
            render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_name(&self) -> String {
 | 
			
		||||
        MeshesDrawTarget::NAME.to_string()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
mod assigned_meshes_draw_target;
 | 
			
		||||
mod meshes_draw_target;
 | 
			
		||||
 | 
			
		||||
pub use assigned_meshes_draw_target::*;
 | 
			
		||||
pub use meshes_draw_target::*;
 | 
			
		||||
@ -1,5 +0,0 @@
 | 
			
		||||
mod draw_target;
 | 
			
		||||
mod draw_targets;
 | 
			
		||||
 | 
			
		||||
pub use draw_target::*;
 | 
			
		||||
pub use draw_targets::*;
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
pub mod batch;
 | 
			
		||||
mod camera;
 | 
			
		||||
pub mod draw;
 | 
			
		||||
pub mod entity;
 | 
			
		||||
pub mod mesh;
 | 
			
		||||
pub mod render_graph;
 | 
			
		||||
@ -16,7 +17,6 @@ pub use renderable::*;
 | 
			
		||||
pub use vertex::Vertex;
 | 
			
		||||
 | 
			
		||||
pub mod base_render_graph;
 | 
			
		||||
pub mod draw_target;
 | 
			
		||||
pub mod pass;
 | 
			
		||||
pub mod pipeline;
 | 
			
		||||
pub mod render_resource;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    pipeline::PipelineDescriptor,
 | 
			
		||||
    render_resource::{RenderResourceId, RenderResourceAssignments},
 | 
			
		||||
    pipeline::{BindGroupDescriptor, PipelineDescriptor},
 | 
			
		||||
    render_resource::{RenderResourceId, RenderResourceSet},
 | 
			
		||||
    renderer::RenderContext,
 | 
			
		||||
};
 | 
			
		||||
use bevy_asset::Handle;
 | 
			
		||||
@ -15,10 +15,9 @@ pub trait RenderPass {
 | 
			
		||||
    fn set_stencil_reference(&mut self, reference: u32);
 | 
			
		||||
    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>);
 | 
			
		||||
    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
 | 
			
		||||
    // TODO: try to somehow take into account the "set" pipeline instead of passing it in here
 | 
			
		||||
    fn set_render_resources(
 | 
			
		||||
    fn set_bind_group(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        pipeline_descriptor: &PipelineDescriptor,
 | 
			
		||||
        render_resource_assignments: &RenderResourceAssignments,
 | 
			
		||||
    ) -> Option<Range<u32>>;
 | 
			
		||||
        bind_group_descriptor: &BindGroupDescriptor,
 | 
			
		||||
        render_resource_set: &RenderResourceSet,
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,18 +1,22 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    draw_target::DrawTarget,
 | 
			
		||||
    pass::{PassDescriptor, TextureAttachment},
 | 
			
		||||
    pipeline::{PipelineCompiler, PipelineDescriptor},
 | 
			
		||||
    pass::{PassDescriptor, RenderPass, TextureAttachment},
 | 
			
		||||
    pipeline::{PipelineAssignments, PipelineCompiler, PipelineDescriptor},
 | 
			
		||||
    render_graph::{Node, ResourceSlotInfo, ResourceSlots},
 | 
			
		||||
    render_resource::{ResourceInfo, RenderResourceAssignments},
 | 
			
		||||
    render_resource::{
 | 
			
		||||
        EntitiesWaitingForAssets, EntityRenderResourceAssignments, RenderResourceAssignments,
 | 
			
		||||
        ResourceInfo,
 | 
			
		||||
    },
 | 
			
		||||
    renderer::RenderContext,
 | 
			
		||||
    shader::Shader,
 | 
			
		||||
    Renderable,
 | 
			
		||||
};
 | 
			
		||||
use bevy_asset::{Assets, Handle};
 | 
			
		||||
use legion::prelude::*;
 | 
			
		||||
use std::ops::Range;
 | 
			
		||||
 | 
			
		||||
pub struct PassNode {
 | 
			
		||||
    descriptor: PassDescriptor,
 | 
			
		||||
    pipelines: Vec<(Handle<PipelineDescriptor>, Vec<Box<dyn DrawTarget>>)>,
 | 
			
		||||
    pipelines: Vec<Handle<PipelineDescriptor>>,
 | 
			
		||||
    inputs: Vec<ResourceSlotInfo>,
 | 
			
		||||
    color_attachment_input_indices: Vec<Option<usize>>,
 | 
			
		||||
    depth_stencil_attachment_input_index: Option<usize>,
 | 
			
		||||
@ -54,12 +58,64 @@ impl PassNode {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_pipeline(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        pipeline_handle: Handle<PipelineDescriptor>,
 | 
			
		||||
        draw_targets: Vec<Box<dyn DrawTarget>>,
 | 
			
		||||
    ) {
 | 
			
		||||
        self.pipelines.push((pipeline_handle, draw_targets));
 | 
			
		||||
    pub fn add_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>) {
 | 
			
		||||
        self.pipelines.push(pipeline_handle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn set_render_resources(
 | 
			
		||||
        render_pass: &mut dyn RenderPass,
 | 
			
		||||
        pipeline_descriptor: &PipelineDescriptor,
 | 
			
		||||
        render_resource_assignments: &RenderResourceAssignments,
 | 
			
		||||
    ) -> Option<Range<u32>> {
 | 
			
		||||
        let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
 | 
			
		||||
        // PERF: vertex buffer lookup comes at a cost when vertex buffers aren't in render_resource_assignments. iterating over render_resource_assignment vertex buffers
 | 
			
		||||
        // would likely be faster
 | 
			
		||||
        let mut indices = None;
 | 
			
		||||
        for (i, vertex_buffer_descriptor) in
 | 
			
		||||
            pipeline_layout.vertex_buffer_descriptors.iter().enumerate()
 | 
			
		||||
        {
 | 
			
		||||
            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
 | 
			
		||||
                );
 | 
			
		||||
                render_pass.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
 | 
			
		||||
                    );
 | 
			
		||||
                    render_pass.set_index_buffer(index_buffer, 0);
 | 
			
		||||
                    render_pass
 | 
			
		||||
                        .get_render_context()
 | 
			
		||||
                        .resources()
 | 
			
		||||
                        .get_resource_info(
 | 
			
		||||
                            index_buffer,
 | 
			
		||||
                            &mut |resource_info| match resource_info {
 | 
			
		||||
                                Some(ResourceInfo::Buffer(Some(buffer_info))) => {
 | 
			
		||||
                                    indices = Some(0..(buffer_info.size / 2) as u32)
 | 
			
		||||
                                }
 | 
			
		||||
                                _ => panic!("expected a buffer type"),
 | 
			
		||||
                            },
 | 
			
		||||
                        );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for bind_group in pipeline_layout.bind_groups.iter() {
 | 
			
		||||
            if let Some(render_resource_set) =
 | 
			
		||||
                render_resource_assignments.get_render_resource_set(bind_group.id)
 | 
			
		||||
            {
 | 
			
		||||
                render_pass.set_bind_group(bind_group, &render_resource_set);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        indices
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -78,6 +134,12 @@ impl Node for PassNode {
 | 
			
		||||
    ) {
 | 
			
		||||
        let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap();
 | 
			
		||||
        let pipelines = resources.get::<Assets<PipelineDescriptor>>().unwrap();
 | 
			
		||||
        let shader_pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
 | 
			
		||||
        let entity_render_resource_assignments =
 | 
			
		||||
            resources.get::<EntityRenderResourceAssignments>().unwrap();
 | 
			
		||||
        let entities_waiting_for_assets = resources.get::<EntitiesWaitingForAssets>().unwrap();
 | 
			
		||||
        let mut render_resource_assignments =
 | 
			
		||||
            resources.get_mut::<RenderResourceAssignments>().unwrap();
 | 
			
		||||
 | 
			
		||||
        for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
 | 
			
		||||
            if let Some(input_index) = self.color_attachment_input_indices[i] {
 | 
			
		||||
@ -94,50 +156,71 @@ impl Node for PassNode {
 | 
			
		||||
                .attachment = TextureAttachment::RenderResource(input.get(input_index).unwrap());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let shaders = resources.get::<Assets<Shader>>().unwrap();
 | 
			
		||||
        for (pipeline_handle, draw_targets) in self.pipelines.iter_mut() {
 | 
			
		||||
            if let Some(compiled_pipelines_iter) =
 | 
			
		||||
                pipeline_compiler.iter_compiled_pipelines(*pipeline_handle)
 | 
			
		||||
            {
 | 
			
		||||
                for compiled_pipeline_handle in compiled_pipelines_iter {
 | 
			
		||||
                    let compiled_pipeline_descriptor =
 | 
			
		||||
                        pipelines.get(compiled_pipeline_handle).unwrap();
 | 
			
		||||
        {
 | 
			
		||||
            let render_resource_context = render_context.resources();
 | 
			
		||||
 | 
			
		||||
                    let pipeline_layout = compiled_pipeline_descriptor.get_layout().unwrap();
 | 
			
		||||
                    {
 | 
			
		||||
                        // TODO: this breaks down in a parallel setting. it needs to change. ideally in a way that
 | 
			
		||||
                        // doesn't require modifying RenderResourceAssignments
 | 
			
		||||
                        let mut render_resource_assignments =
 | 
			
		||||
                            resources.get_mut::<RenderResourceAssignments>().unwrap();
 | 
			
		||||
                        for bind_group in pipeline_layout.bind_groups.iter() {
 | 
			
		||||
                            render_resource_assignments.update_render_resource_set_id(bind_group);
 | 
			
		||||
            // TODO: try merging the two pipeline loops below
 | 
			
		||||
            let shaders = resources.get::<Assets<Shader>>().unwrap();
 | 
			
		||||
            for pipeline_handle in self.pipelines.iter() {
 | 
			
		||||
                if let Some(compiled_pipelines_iter) =
 | 
			
		||||
                    pipeline_compiler.iter_compiled_pipelines(*pipeline_handle)
 | 
			
		||||
                {
 | 
			
		||||
                    for compiled_pipeline_handle in compiled_pipelines_iter {
 | 
			
		||||
                        let compiled_pipeline_descriptor =
 | 
			
		||||
                            pipelines.get(compiled_pipeline_handle).unwrap();
 | 
			
		||||
 | 
			
		||||
                        let pipeline_layout = compiled_pipeline_descriptor.get_layout().unwrap();
 | 
			
		||||
                        {
 | 
			
		||||
                            // TODO: this breaks down in a parallel setting. it needs to change. ideally in a way that
 | 
			
		||||
                            // doesn't require modifying RenderResourceAssignments
 | 
			
		||||
                            for bind_group in pipeline_layout.bind_groups.iter() {
 | 
			
		||||
                                render_resource_assignments
 | 
			
		||||
                                    .update_render_resource_set_id(bind_group);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    render_context.resources().create_render_pipeline(
 | 
			
		||||
                        *compiled_pipeline_handle,
 | 
			
		||||
                        &compiled_pipeline_descriptor,
 | 
			
		||||
                        &shaders,
 | 
			
		||||
                    );
 | 
			
		||||
                    for draw_target in draw_targets.iter_mut() {
 | 
			
		||||
                        draw_target.setup(
 | 
			
		||||
                            world,
 | 
			
		||||
                            resources,
 | 
			
		||||
                            render_context,
 | 
			
		||||
                        render_resource_context.create_render_pipeline(
 | 
			
		||||
                            *compiled_pipeline_handle,
 | 
			
		||||
                            compiled_pipeline_descriptor,
 | 
			
		||||
                            &compiled_pipeline_descriptor,
 | 
			
		||||
                            &shaders,
 | 
			
		||||
                        );
 | 
			
		||||
 | 
			
		||||
                        render_resource_context.setup_bind_groups(
 | 
			
		||||
                            compiled_pipeline_descriptor,
 | 
			
		||||
                            &render_resource_assignments,
 | 
			
		||||
                        );
 | 
			
		||||
                        let assigned_render_resource_assignments = shader_pipeline_assignments
 | 
			
		||||
                            .assignments
 | 
			
		||||
                            .get(&compiled_pipeline_handle);
 | 
			
		||||
                        if let Some(assigned_render_resource_assignments) =
 | 
			
		||||
                            assigned_render_resource_assignments
 | 
			
		||||
                        {
 | 
			
		||||
                            for assignment_id in assigned_render_resource_assignments.iter() {
 | 
			
		||||
                                let entity = entity_render_resource_assignments
 | 
			
		||||
                                    .get(*assignment_id)
 | 
			
		||||
                                    .unwrap();
 | 
			
		||||
                                let renderable =
 | 
			
		||||
                                    world.get_component::<Renderable>(*entity).unwrap();
 | 
			
		||||
                                if !renderable.is_visible || renderable.is_instanced {
 | 
			
		||||
                                    continue;
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                render_resource_context.setup_bind_groups(
 | 
			
		||||
                                    compiled_pipeline_descriptor,
 | 
			
		||||
                                    &renderable.render_resource_assignments,
 | 
			
		||||
                                );
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let render_resource_assignments = resources.get::<RenderResourceAssignments>().unwrap();
 | 
			
		||||
        render_context.begin_pass(
 | 
			
		||||
            &self.descriptor,
 | 
			
		||||
            &render_resource_assignments,
 | 
			
		||||
            &mut |render_pass| {
 | 
			
		||||
                for (pipeline_handle, draw_targets) in self.pipelines.iter() {
 | 
			
		||||
                for pipeline_handle in self.pipelines.iter() {
 | 
			
		||||
                    if let Some(compiled_pipelines_iter) =
 | 
			
		||||
                        pipeline_compiler.iter_compiled_pipelines(*pipeline_handle)
 | 
			
		||||
                    {
 | 
			
		||||
@ -145,14 +228,45 @@ impl Node for PassNode {
 | 
			
		||||
                            let compiled_pipeline_descriptor =
 | 
			
		||||
                                pipelines.get(compiled_pipeline_handle).unwrap();
 | 
			
		||||
                            render_pass.set_pipeline(*compiled_pipeline_handle);
 | 
			
		||||
                            for draw_target in draw_targets.iter() {
 | 
			
		||||
                                draw_target.draw(
 | 
			
		||||
                                    world,
 | 
			
		||||
                                    resources,
 | 
			
		||||
                                    render_pass,
 | 
			
		||||
                                    *compiled_pipeline_handle,
 | 
			
		||||
                                    compiled_pipeline_descriptor,
 | 
			
		||||
                                );
 | 
			
		||||
 | 
			
		||||
                            // set global render resources
 | 
			
		||||
                            Self::set_render_resources(
 | 
			
		||||
                                render_pass,
 | 
			
		||||
                                compiled_pipeline_descriptor,
 | 
			
		||||
                                &render_resource_assignments,
 | 
			
		||||
                            );
 | 
			
		||||
 | 
			
		||||
                            // draw entities assigned to this pipeline
 | 
			
		||||
                            let assigned_render_resource_assignments = shader_pipeline_assignments
 | 
			
		||||
                                .assignments
 | 
			
		||||
                                .get(&compiled_pipeline_handle);
 | 
			
		||||
 | 
			
		||||
                            if let Some(assigned_render_resource_assignments) =
 | 
			
		||||
                                assigned_render_resource_assignments
 | 
			
		||||
                            {
 | 
			
		||||
                                for assignment_id in assigned_render_resource_assignments.iter() {
 | 
			
		||||
                                    // TODO: hopefully legion has better random access apis that are more like queries?
 | 
			
		||||
                                    let entity = entity_render_resource_assignments
 | 
			
		||||
                                        .get(*assignment_id)
 | 
			
		||||
                                        .unwrap();
 | 
			
		||||
                                    let renderable =
 | 
			
		||||
                                        world.get_component::<Renderable>(*entity).unwrap();
 | 
			
		||||
                                    if !renderable.is_visible
 | 
			
		||||
                                        || renderable.is_instanced
 | 
			
		||||
                                        || entities_waiting_for_assets.contains(entity)
 | 
			
		||||
                                    {
 | 
			
		||||
                                        continue;
 | 
			
		||||
                                    }
 | 
			
		||||
 | 
			
		||||
                                    // set local render resources
 | 
			
		||||
                                    if let Some(indices) = Self::set_render_resources(
 | 
			
		||||
                                        render_pass,
 | 
			
		||||
                                        compiled_pipeline_descriptor,
 | 
			
		||||
                                        &renderable.render_resource_assignments,
 | 
			
		||||
                                    ) {
 | 
			
		||||
                                        render_pass.draw_indexed(indices, 0, 0..1);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,6 @@ use crate::{ColorMaterial, Quad, TextureAtlas, TextureAtlasSprite};
 | 
			
		||||
use bevy_asset::{Assets, Handle};
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    base_render_graph,
 | 
			
		||||
    draw_target::AssignedMeshesDrawTarget,
 | 
			
		||||
    pipeline::{state_descriptors::*, PipelineDescriptor},
 | 
			
		||||
    render_graph::{
 | 
			
		||||
        nodes::{AssetUniformNode, PassNode, UniformNode},
 | 
			
		||||
@ -153,14 +152,8 @@ impl SpriteRenderGraphBuilder for RenderGraph {
 | 
			
		||||
        let main_pass: &mut PassNode = self
 | 
			
		||||
            .get_node_mut(base_render_graph::node::MAIN_PASS)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        main_pass.add_pipeline(
 | 
			
		||||
            SPRITE_PIPELINE_HANDLE,
 | 
			
		||||
            vec![Box::new(AssignedMeshesDrawTarget)],
 | 
			
		||||
        );
 | 
			
		||||
        main_pass.add_pipeline(
 | 
			
		||||
            SPRITE_SHEET_PIPELINE_HANDLE,
 | 
			
		||||
            vec![Box::new(AssignedMeshesDrawTarget)],
 | 
			
		||||
        );
 | 
			
		||||
        main_pass.add_pipeline(SPRITE_PIPELINE_HANDLE);
 | 
			
		||||
        main_pass.add_pipeline(SPRITE_SHEET_PIPELINE_HANDLE);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,6 @@
 | 
			
		||||
use bevy_asset::{Assets, Handle};
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    base_render_graph,
 | 
			
		||||
    draw_target::AssignedMeshesDrawTarget,
 | 
			
		||||
    pipeline::{state_descriptors::*, PipelineDescriptor},
 | 
			
		||||
    render_graph::{
 | 
			
		||||
        nodes::{CameraNode, PassNode},
 | 
			
		||||
@ -83,7 +82,7 @@ impl UiRenderGraphBuilder for RenderGraph {
 | 
			
		||||
        let main_pass: &mut PassNode = self
 | 
			
		||||
            .get_node_mut(base_render_graph::node::MAIN_PASS)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        main_pass.add_pipeline(UI_PIPELINE_HANDLE, vec![Box::new(AssignedMeshesDrawTarget)]);
 | 
			
		||||
        main_pass.add_pipeline(UI_PIPELINE_HANDLE);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,12 +6,12 @@ use bevy_render::{
 | 
			
		||||
        PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor,
 | 
			
		||||
        RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
 | 
			
		||||
    },
 | 
			
		||||
    render_resource::{RenderResourceId, RenderResourceAssignment, RenderResourceAssignments},
 | 
			
		||||
    render_resource::{RenderResourceAssignment, RenderResourceAssignments, RenderResourceId},
 | 
			
		||||
    renderer::{RenderContext, RenderResourceContext},
 | 
			
		||||
    texture::Extent3d,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use std::{collections::HashMap, sync::Arc};
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
pub struct LazyCommandEncoder {
 | 
			
		||||
@ -138,10 +138,10 @@ impl RenderContext for WgpuRenderContext {
 | 
			
		||||
                &mut encoder,
 | 
			
		||||
            );
 | 
			
		||||
            let mut wgpu_render_pass = WgpuRenderPass {
 | 
			
		||||
                render_context: self,
 | 
			
		||||
                render_pass,
 | 
			
		||||
                render_context: self,
 | 
			
		||||
                render_resources: refs,
 | 
			
		||||
                bound_bind_groups: HashMap::default(),
 | 
			
		||||
                pipeline_descriptor: None,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            run_pass(&mut wgpu_render_pass);
 | 
			
		||||
 | 
			
		||||
@ -2,19 +2,17 @@ use crate::{renderer::WgpuRenderContext, WgpuResourceRefs};
 | 
			
		||||
use bevy_asset::Handle;
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    pass::RenderPass,
 | 
			
		||||
    pipeline::PipelineDescriptor,
 | 
			
		||||
    render_resource::{
 | 
			
		||||
        RenderResourceId, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
 | 
			
		||||
    },
 | 
			
		||||
    pipeline::{BindGroupDescriptor, PipelineDescriptor},
 | 
			
		||||
    render_resource::{RenderResourceId, RenderResourceSet},
 | 
			
		||||
    renderer::RenderContext,
 | 
			
		||||
};
 | 
			
		||||
use std::{collections::HashMap, ops::Range};
 | 
			
		||||
use std::ops::Range;
 | 
			
		||||
 | 
			
		||||
pub struct WgpuRenderPass<'a> {
 | 
			
		||||
    pub render_pass: wgpu::RenderPass<'a>,
 | 
			
		||||
    pub render_context: &'a WgpuRenderContext,
 | 
			
		||||
    pub render_resources: WgpuResourceRefs<'a>,
 | 
			
		||||
    pub bound_bind_groups: HashMap<u32, RenderResourceSetId>,
 | 
			
		||||
    pub pipeline_descriptor: Option<&'a PipelineDescriptor>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> RenderPass for WgpuRenderPass<'a> {
 | 
			
		||||
@ -51,102 +49,42 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
 | 
			
		||||
        self.render_pass.draw(vertices, instances);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn set_render_resources(
 | 
			
		||||
    fn set_bind_group(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        pipeline_descriptor: &PipelineDescriptor,
 | 
			
		||||
        render_resource_assignments: &RenderResourceAssignments,
 | 
			
		||||
    ) -> Option<Range<u32>> {
 | 
			
		||||
        let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
 | 
			
		||||
        // PERF: vertex buffer lookup comes at a cost when vertex buffers aren't in render_resource_assignments. iterating over render_resource_assignment vertex buffers
 | 
			
		||||
        // would likely be faster
 | 
			
		||||
        let mut indices = None;
 | 
			
		||||
        for (i, vertex_buffer_descriptor) in
 | 
			
		||||
            pipeline_layout.vertex_buffer_descriptors.iter().enumerate()
 | 
			
		||||
        bind_group_descriptor: &BindGroupDescriptor,
 | 
			
		||||
        render_resource_set: &RenderResourceSet,
 | 
			
		||||
    ) {
 | 
			
		||||
        if let Some(bind_group_info) = self
 | 
			
		||||
            .render_resources
 | 
			
		||||
            .bind_groups
 | 
			
		||||
            .get(&bind_group_descriptor.id)
 | 
			
		||||
        {
 | 
			
		||||
            if let Some((vertex_buffer, index_buffer)) =
 | 
			
		||||
                render_resource_assignments.get_vertex_buffer(&vertex_buffer_descriptor.name)
 | 
			
		||||
            if let Some(wgpu_bind_group) = bind_group_info.bind_groups.get(&render_resource_set.id)
 | 
			
		||||
            {
 | 
			
		||||
                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
 | 
			
		||||
                    );
 | 
			
		||||
                    self.set_index_buffer(index_buffer, 0);
 | 
			
		||||
                    self.render_context.resources().get_resource_info(
 | 
			
		||||
                        index_buffer,
 | 
			
		||||
                        &mut |resource_info| match resource_info {
 | 
			
		||||
                            Some(ResourceInfo::Buffer(Some(buffer_info))) => {
 | 
			
		||||
                                indices = Some(0..(buffer_info.size / 2) as u32)
 | 
			
		||||
                            }
 | 
			
		||||
                            _ => panic!("expected a buffer type"),
 | 
			
		||||
                        },
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for bind_group in pipeline_layout.bind_groups.iter() {
 | 
			
		||||
            if let Some(resource_set) =
 | 
			
		||||
                render_resource_assignments.get_render_resource_set(bind_group.id)
 | 
			
		||||
            {
 | 
			
		||||
                if let Some(bind_group_info) = self.render_resources.bind_groups.get(&bind_group.id)
 | 
			
		||||
                const EMPTY: &'static [u32] = &[];
 | 
			
		||||
                let dynamic_uniform_indices = if let Some(ref dynamic_uniform_indices) =
 | 
			
		||||
                    render_resource_set.dynamic_uniform_indices
 | 
			
		||||
                {
 | 
			
		||||
                    if let Some(wgpu_bind_group) = bind_group_info.bind_groups.get(&resource_set.id)
 | 
			
		||||
                    {
 | 
			
		||||
                        const EMPTY: &'static [u32] = &[];
 | 
			
		||||
                        let dynamic_uniform_indices = if let Some(ref dynamic_uniform_indices) =
 | 
			
		||||
                            resource_set.dynamic_uniform_indices
 | 
			
		||||
                        {
 | 
			
		||||
                            dynamic_uniform_indices.as_slice()
 | 
			
		||||
                        } else {
 | 
			
		||||
                            EMPTY
 | 
			
		||||
                        };
 | 
			
		||||
 | 
			
		||||
                        // don't bind bind groups if they are already set
 | 
			
		||||
                        // TODO: these checks come at a performance cost. make sure it's worth it!
 | 
			
		||||
                        if let Some(bound_render_resource_set) =
 | 
			
		||||
                            self.bound_bind_groups.get(&bind_group.index)
 | 
			
		||||
                        {
 | 
			
		||||
                            if *bound_render_resource_set == resource_set.id
 | 
			
		||||
                                && dynamic_uniform_indices.len() == 0
 | 
			
		||||
                            {
 | 
			
		||||
                                continue;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if dynamic_uniform_indices.len() == 0 {
 | 
			
		||||
                            self.bound_bind_groups
 | 
			
		||||
                                .insert(bind_group.index, resource_set.id);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            self.bound_bind_groups.remove(&bind_group.index);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        log::trace!(
 | 
			
		||||
                            "set bind group {} {:?}: {:?}",
 | 
			
		||||
                            bind_group.index,
 | 
			
		||||
                            dynamic_uniform_indices,
 | 
			
		||||
                            resource_set.id
 | 
			
		||||
                        );
 | 
			
		||||
                        self.render_pass.set_bind_group(
 | 
			
		||||
                            bind_group.index,
 | 
			
		||||
                            wgpu_bind_group,
 | 
			
		||||
                            dynamic_uniform_indices,
 | 
			
		||||
                        );
 | 
			
		||||
                    }
 | 
			
		||||
                    dynamic_uniform_indices.as_slice()
 | 
			
		||||
                } else {
 | 
			
		||||
                    EMPTY
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                log::trace!(
 | 
			
		||||
                    "set bind group {:?} {:?}: {:?}",
 | 
			
		||||
                    bind_group_descriptor.id,
 | 
			
		||||
                    dynamic_uniform_indices,
 | 
			
		||||
                    render_resource_set.id
 | 
			
		||||
                );
 | 
			
		||||
                self.render_pass.set_bind_group(
 | 
			
		||||
                    bind_group_descriptor.index,
 | 
			
		||||
                    wgpu_bind_group,
 | 
			
		||||
                    dynamic_uniform_indices,
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        indices
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn set_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>) {
 | 
			
		||||
        let pipeline = self.render_resources.render_pipelines.get(&pipeline_handle).expect(
 | 
			
		||||
            "Attempted to use a pipeline that does not exist in this RenderPass's RenderContext",
 | 
			
		||||
 | 
			
		||||
@ -55,10 +55,7 @@ fn setup(
 | 
			
		||||
 | 
			
		||||
        render_graph.add_system_node("my_material", AssetUniformNode::<MyMaterial>::new(true));
 | 
			
		||||
        let main_pass: &mut PassNode = render_graph.get_node_mut("main_pass").unwrap();
 | 
			
		||||
        main_pass.add_pipeline(
 | 
			
		||||
            pipeline_handle,
 | 
			
		||||
            vec![Box::new(draw_target::AssignedMeshesDrawTarget)],
 | 
			
		||||
        );
 | 
			
		||||
        main_pass.add_pipeline(pipeline_handle);
 | 
			
		||||
        pipeline_handle
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -65,10 +65,7 @@ fn setup(
 | 
			
		||||
        }));
 | 
			
		||||
        render_graph.add_system_node("my_material", AssetUniformNode::<MyMaterial>::new(true));
 | 
			
		||||
        let main_pass: &mut PassNode = render_graph.get_node_mut("main_pass").unwrap();
 | 
			
		||||
        main_pass.add_pipeline(
 | 
			
		||||
            pipeline_handle,
 | 
			
		||||
            vec![Box::new(draw_target::AssignedMeshesDrawTarget)],
 | 
			
		||||
        );
 | 
			
		||||
        main_pass.add_pipeline(pipeline_handle);
 | 
			
		||||
        pipeline_handle
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,6 @@ pub use crate::{
 | 
			
		||||
    pbr::{entity::*, light::Light, material::StandardMaterial},
 | 
			
		||||
    property::{DynamicProperties, Properties, PropertiesVal, Property, PropertyVal},
 | 
			
		||||
    render::{
 | 
			
		||||
        draw_target,
 | 
			
		||||
        entity::*,
 | 
			
		||||
        mesh::{shape, Mesh},
 | 
			
		||||
        pipeline::PipelineDescriptor,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user