diff --git a/src/render/draw_target/draw_target.rs b/src/render/draw_target/draw_target.rs index 0a261888f8..6d8c6e96a2 100644 --- a/src/render/draw_target/draw_target.rs +++ b/src/render/draw_target/draw_target.rs @@ -22,6 +22,7 @@ pub trait DrawTarget { _resources: &Resources, _renderer: &mut dyn Renderer, _pipeline_handle: Handle, + _pipeline_descriptor: &PipelineDescriptor, ) { } fn get_name(&self) -> String; diff --git a/src/render/draw_target/draw_targets/assigned_batches_draw_target.rs b/src/render/draw_target/draw_targets/assigned_batches_draw_target.rs index 7de3a266e1..a53bd41202 100644 --- a/src/render/draw_target/draw_targets/assigned_batches_draw_target.rs +++ b/src/render/draw_target/draw_targets/assigned_batches_draw_target.rs @@ -1,5 +1,5 @@ use crate::{ - asset::{AssetStorage, Handle}, + asset::Handle, legion::prelude::*, prelude::Renderable, render::{ @@ -68,17 +68,17 @@ impl DrawTarget for AssignedBatchesDrawTarget { resources: &Resources, renderer: &mut dyn Renderer, pipeline_handle: Handle, + pipeline_descriptor: &PipelineDescriptor, ) { let mut asset_batches = resources.get_mut::().unwrap(); - let pipeline_storage = resources.get::>().unwrap(); - let pipeline_descriptor = pipeline_storage.get(&pipeline_handle).unwrap(); let mut global_render_resource_assignments = resources.get_mut::().unwrap(); log::debug!( - "setting up batch bind groups for pipeline: {:?}", - pipeline_handle + "setting up batch bind groups for pipeline: {:?} {:?}", + pipeline_handle, + pipeline_descriptor.name, ); log::trace!("setting up global bind groups"); renderer.setup_bind_groups(&mut global_render_resource_assignments, pipeline_descriptor); diff --git a/src/render/draw_target/draw_targets/assigned_meshes_draw_target.rs b/src/render/draw_target/draw_targets/assigned_meshes_draw_target.rs index c4a49994d1..28ad2e588b 100644 --- a/src/render/draw_target/draw_targets/assigned_meshes_draw_target.rs +++ b/src/render/draw_target/draw_targets/assigned_meshes_draw_target.rs @@ -1,5 +1,5 @@ use crate::{ - asset::{AssetStorage, Handle}, + asset::Handle, legion::prelude::*, render::{ draw_target::DrawTarget, @@ -83,6 +83,7 @@ impl DrawTarget for AssignedMeshesDrawTarget { resources: &Resources, renderer: &mut dyn Renderer, pipeline_handle: Handle, + pipeline_descriptor: &PipelineDescriptor, ) { let shader_pipeline_assignments = resources.get::().unwrap(); let entity_render_resource_assignments = @@ -90,14 +91,11 @@ impl DrawTarget for AssignedMeshesDrawTarget { let assigned_render_resource_assignments = shader_pipeline_assignments .assignments .get(&pipeline_handle); - let pipeline_storage = resources.get::>().unwrap(); - let pipeline_descriptor = pipeline_storage.get(&pipeline_handle).unwrap(); let mut global_render_resource_assignments = resources.get_mut::().unwrap(); renderer.setup_bind_groups(&mut global_render_resource_assignments, pipeline_descriptor); 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(); diff --git a/src/render/draw_target/draw_targets/ui_draw_target.rs b/src/render/draw_target/draw_targets/ui_draw_target.rs index 643a6c39ae..56f8a2b386 100644 --- a/src/render/draw_target/draw_targets/ui_draw_target.rs +++ b/src/render/draw_target/draw_targets/ui_draw_target.rs @@ -1,5 +1,5 @@ use crate::{ - asset::{Asset, AssetStorage, Handle}, + asset::{Asset, Handle}, legion::prelude::*, math, prelude::MeshType, @@ -72,7 +72,8 @@ impl DrawTarget for UiDrawTarget { _world: &mut World, resources: &Resources, renderer: &mut dyn Renderer, - pipeline_handle: Handle, + _pipeline_handle: Handle, + pipeline_descriptor: &PipelineDescriptor, ) { // don't create meshes if they have already been created if let Some(_) = self.mesh_vertex_buffer { @@ -100,8 +101,6 @@ impl DrawTarget for UiDrawTarget { let mut global_render_resource_assignments = resources.get_mut::().unwrap(); - let pipeline_storage = resources.get::>().unwrap(); - let pipeline_descriptor = pipeline_storage.get(&pipeline_handle).unwrap(); renderer.setup_bind_groups(&mut global_render_resource_assignments, pipeline_descriptor); } fn get_name(&self) -> String { diff --git a/src/render/pipeline/pipeline_compiler.rs b/src/render/pipeline/pipeline_compiler.rs index c73362eaf7..543c966cfc 100644 --- a/src/render/pipeline/pipeline_compiler.rs +++ b/src/render/pipeline/pipeline_compiler.rs @@ -1,9 +1,8 @@ -use super::{BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType}; +use super::{BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType, VertexBufferDescriptors}; use crate::{ asset::{AssetStorage, Handle}, prelude::{Renderable, Resources, Shader, World}, render::{ - render_graph::RenderGraph, render_resource::{ BufferInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo, }, @@ -32,7 +31,7 @@ impl PipelineCompiler { fn reflect_layout( shader_storage: &AssetStorage, - render_graph: &RenderGraph, + vertex_buffer_descriptors: &VertexBufferDescriptors, pipeline_descriptor: &mut PipelineDescriptor, renderer: &dyn Renderer, render_resource_assignments: &RenderResourceAssignments, @@ -52,7 +51,7 @@ impl PipelineCompiler { } let mut layout = PipelineLayout::from_shader_layouts(&mut layouts); - layout.sync_vertex_buffer_descriptors_with_render_graph(render_graph); + layout.sync_vertex_buffer_descriptors(vertex_buffer_descriptors); // set binding uniforms to dynamic if render resource assignments use dynamic // TODO: this breaks down if different assignments have different "dynamic" status or if the dynamic status changes. @@ -113,7 +112,7 @@ impl PipelineCompiler { fn compile_pipeline( &mut self, - render_graph: &RenderGraph, + vertex_buffer_descriptors: &VertexBufferDescriptors, shader_storage: &mut AssetStorage, renderer: &dyn Renderer, pipeline_descriptor: &PipelineDescriptor, @@ -140,7 +139,7 @@ impl PipelineCompiler { Self::reflect_layout( shader_storage, - render_graph, + vertex_buffer_descriptors, &mut compiled_pipeline_descriptor, renderer, render_resource_assignments, @@ -151,7 +150,7 @@ impl PipelineCompiler { fn update_shader_assignments( &mut self, - render_graph: &RenderGraph, + vertex_buffer_descriptors: &VertexBufferDescriptors, shader_pipeline_assignments: &mut ShaderPipelineAssignments, renderer: &dyn Renderer, pipeline_storage: &mut AssetStorage, @@ -177,7 +176,7 @@ impl PipelineCompiler { } else { let pipeline_descriptor = pipeline_storage.get(pipeline_handle).unwrap(); let compiled_pipeline = self.compile_pipeline( - render_graph, + vertex_buffer_descriptors, shader_storage, renderer, pipeline_descriptor, @@ -248,7 +247,7 @@ pub fn update_shader_assignments( resources.get_mut::().unwrap(); let mut pipeline_compiler = resources.get_mut::().unwrap(); let mut shader_storage = resources.get_mut::>().unwrap(); - let mut render_graph = resources.get_mut::().unwrap(); + let vertex_buffer_descriptors = resources.get::().unwrap(); let mut pipeline_descriptor_storage = resources .get_mut::>() .unwrap(); @@ -264,7 +263,7 @@ pub fn update_shader_assignments( } pipeline_compiler.update_shader_assignments( - &mut render_graph, + &vertex_buffer_descriptors, &mut shader_pipeline_assignments, renderer, &mut pipeline_descriptor_storage, diff --git a/src/render/pipeline/pipeline_layout.rs b/src/render/pipeline/pipeline_layout.rs index 36ea976f20..5d7a83e5cf 100644 --- a/src/render/pipeline/pipeline_layout.rs +++ b/src/render/pipeline/pipeline_layout.rs @@ -1,5 +1,5 @@ -use super::{BindGroupDescriptor, VertexBufferDescriptor}; -use crate::render::{render_graph::RenderGraph, shader::ShaderLayout}; +use super::{BindGroupDescriptor, VertexBufferDescriptor, VertexBufferDescriptors}; +use crate::render::shader::ShaderLayout; use std::{collections::HashMap, hash::Hash}; #[derive(Clone, Debug, Default)] @@ -56,10 +56,13 @@ impl PipelineLayout { } } - pub fn sync_vertex_buffer_descriptors_with_render_graph(&mut self, render_graph: &RenderGraph) { + pub fn sync_vertex_buffer_descriptors( + &mut self, + vertex_buffer_descriptors: &VertexBufferDescriptors, + ) { for vertex_buffer_descriptor in self.vertex_buffer_descriptors.iter_mut() { if let Some(graph_descriptor) = - render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name) + vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) { vertex_buffer_descriptor.sync_with_descriptor(graph_descriptor); } else { diff --git a/src/render/pipeline/vertex_buffer_descriptor.rs b/src/render/pipeline/vertex_buffer_descriptor.rs index a0d7de6085..30dd9f4d02 100644 --- a/src/render/pipeline/vertex_buffer_descriptor.rs +++ b/src/render/pipeline/vertex_buffer_descriptor.rs @@ -1,4 +1,5 @@ use super::VertexFormat; +use std::collections::HashMap; #[derive(Clone, Debug, Eq, PartialEq)] pub struct VertexBufferDescriptor { @@ -41,3 +42,21 @@ pub struct VertexAttributeDescriptor { pub format: VertexFormat, pub shader_location: u32, } + +#[derive(Default)] +pub struct VertexBufferDescriptors { + pub descriptors: HashMap, +} + +impl VertexBufferDescriptors { + pub fn set(&mut self, vertex_buffer_descriptor: VertexBufferDescriptor) { + self.descriptors.insert( + vertex_buffer_descriptor.name.to_string(), + vertex_buffer_descriptor, + ); + } + + pub fn get(&self, name: &str) -> Option<&VertexBufferDescriptor> { + self.descriptors.get(name) + } +} diff --git a/src/render/render_graph/render_graph.rs b/src/render/render_graph/render_graph.rs index c97db8ed7e..3750c328f9 100644 --- a/src/render/render_graph/render_graph.rs +++ b/src/render/render_graph/render_graph.rs @@ -1,12 +1,13 @@ use super::RenderGraphBuilder; use crate::{ asset::{AssetStorage, Handle}, - prelude::Shader, + prelude::{Resources, Shader, World}, render::{ draw_target::DrawTarget, pass::PassDescriptor, - pipeline::{PipelineDescriptor, VertexBufferDescriptor}, + pipeline::{PipelineCompiler, PipelineDescriptor}, render_resource::ResourceProvider, + renderer::Renderer, texture::TextureDescriptor, }, }; @@ -21,7 +22,6 @@ pub struct RenderGraph { pub resource_providers: Vec>, pub queued_textures: Vec<(String, TextureDescriptor)>, pub draw_targets: HashMap>, - pub vertex_buffer_descriptors: HashMap, } impl RenderGraph { @@ -49,17 +49,52 @@ impl RenderGraph { pass_pipelines.push(pipeline); } - pub fn set_vertex_buffer_descriptor( + pub fn setup_pipeline_draw_targets( &mut self, - vertex_buffer_descriptor: VertexBufferDescriptor, + world: &mut World, + resources: &Resources, + renderer: &mut dyn Renderer, ) { - self.vertex_buffer_descriptors.insert( - vertex_buffer_descriptor.name.to_string(), - vertex_buffer_descriptor, - ); - } + let shader_storage = resources.get::>().unwrap(); + let pipeline_compiler = resources.get::().unwrap(); - pub fn get_vertex_buffer_descriptor(&self, name: &str) -> Option<&VertexBufferDescriptor> { - self.vertex_buffer_descriptors.get(name) + for (pass_name, _pass_descriptor) in self.pass_descriptors.iter() { + if let Some(pass_pipelines) = self.pass_pipelines.get(pass_name) { + for pass_pipeline in pass_pipelines.iter() { + if let Some(compiled_pipelines_iter) = + pipeline_compiler.iter_compiled_pipelines(*pass_pipeline) + { + for compiled_pipeline_handle in compiled_pipelines_iter { + let mut pipeline_storage = resources + .get_mut::>() + .unwrap(); + let compiled_pipeline_descriptor = + pipeline_storage.get_mut(compiled_pipeline_handle).unwrap(); + + // create wgpu pipeline if it doesn't exist + renderer.setup_render_pipeline( + *compiled_pipeline_handle, + compiled_pipeline_descriptor, + &shader_storage, + ); + + // setup pipeline draw targets + for draw_target_name in compiled_pipeline_descriptor.draw_targets.iter() + { + let draw_target = + self.draw_targets.get_mut(draw_target_name).unwrap(); + draw_target.setup( + world, + resources, + renderer, + *compiled_pipeline_handle, + compiled_pipeline_descriptor, + ); + } + } + } + } + } + } } } diff --git a/src/render/render_plugin.rs b/src/render/render_plugin.rs index 541fb3bc4f..c45c22b082 100644 --- a/src/render/render_plugin.rs +++ b/src/render/render_plugin.rs @@ -3,7 +3,7 @@ use super::{ AssignedBatchesDrawTarget, AssignedMeshesDrawTarget, MeshesDrawTarget, UiDrawTarget, }, pass::passes::ForwardPassBuilder, - pipeline::{pipelines::ForwardPipelineBuilder, PipelineCompiler, ShaderPipelineAssignments}, + pipeline::{pipelines::ForwardPipelineBuilder, PipelineCompiler, ShaderPipelineAssignments, VertexBufferDescriptors}, render_graph::RenderGraph, render_resource::{ build_entity_render_resource_assignments_system, @@ -62,6 +62,7 @@ impl AppPlugin for RenderPlugin { .add_resource(AssetStorage::::new()) .add_resource(AssetStorage::::new()) .add_resource(ShaderPipelineAssignments::new()) + .add_resource(VertexBufferDescriptors::default()) .add_resource(PipelineCompiler::new()) .add_resource(RenderResourceAssignments::default()) .add_resource(EntityRenderResourceAssignments::default()) diff --git a/src/render/render_resource/resource_providers/mesh_resource_provider.rs b/src/render/render_resource/resource_providers/mesh_resource_provider.rs index 364675c769..bb6a883665 100644 --- a/src/render/render_resource/resource_providers/mesh_resource_provider.rs +++ b/src/render/render_resource/resource_providers/mesh_resource_provider.rs @@ -3,7 +3,7 @@ use crate::{ prelude::Renderable, render::{ mesh::Mesh, - render_graph::RenderGraph, + pipeline::VertexBufferDescriptors, render_resource::{ AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments, ResourceProvider, }, @@ -92,9 +92,8 @@ impl ResourceProvider for MeshResourceProvider { _world: &mut World, resources: &Resources, ) { - let mut render_graph = resources.get_mut::().unwrap(); - render_graph - .set_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor().cloned().unwrap()); + let mut vertex_buffer_descriptors = resources.get_mut::().unwrap(); + vertex_buffer_descriptors.set(Vertex::get_vertex_buffer_descriptor().cloned().unwrap()); } fn update(&mut self, _renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { diff --git a/src/render/render_resource/resource_providers/ui_resource_provider.rs b/src/render/render_resource/resource_providers/ui_resource_provider.rs index d1756e3839..1930818a6d 100644 --- a/src/render/render_resource/resource_providers/ui_resource_provider.rs +++ b/src/render/render_resource/resource_providers/ui_resource_provider.rs @@ -2,7 +2,7 @@ use crate::{ ecs, prelude::Node, render::{ - render_graph::RenderGraph, + pipeline::VertexBufferDescriptors, render_resource::{ resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, ResourceProvider, @@ -113,9 +113,8 @@ impl ResourceProvider for UiResourceProvider { _world: &mut World, resources: &Resources, ) { - let mut render_graph = resources.get_mut::().unwrap(); - render_graph - .set_vertex_buffer_descriptor(Rect::get_vertex_buffer_descriptor().cloned().unwrap()); + let mut vertex_buffer_descriptors = resources.get_mut::().unwrap(); + vertex_buffer_descriptors.set(Rect::get_vertex_buffer_descriptor().cloned().unwrap()); } fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { diff --git a/src/render/render_resource/resource_providers/uniform_resource_provider.rs b/src/render/render_resource/resource_providers/uniform_resource_provider.rs index d36ad50495..f4fabf488e 100644 --- a/src/render/render_resource/resource_providers/uniform_resource_provider.rs +++ b/src/render/render_resource/resource_providers/uniform_resource_provider.rs @@ -1,7 +1,7 @@ use crate::{ asset::{AssetStorage, Handle}, render::{ - render_graph::RenderGraph, + pipeline::VertexBufferDescriptors, render_resource::{ AssetBatchers, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, ResourceInfo, ResourceProvider, @@ -543,12 +543,14 @@ where } } - fn initialize_vertex_buffer_descriptor(&self, render_graph: &mut RenderGraph) { + fn initialize_vertex_buffer_descriptor( + &self, + vertex_buffer_descriptors: &mut VertexBufferDescriptors, + ) { let vertex_buffer_descriptor = T::get_vertex_buffer_descriptor(); if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor { - if let None = render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name) - { - render_graph.set_vertex_buffer_descriptor(vertex_buffer_descriptor.clone()); + if let None = vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) { + vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone()); } } } @@ -601,8 +603,8 @@ where world: &mut World, resources: &Resources, ) { - let mut render_graph = resources.get_mut::().unwrap(); - self.initialize_vertex_buffer_descriptor(&mut render_graph); + let mut vertex_buffer_descriptors = resources.get_mut::().unwrap(); + self.initialize_vertex_buffer_descriptor(&mut vertex_buffer_descriptors); self.update(renderer, world, resources); } diff --git a/src/render/renderer/renderer.rs b/src/render/renderer/renderer.rs index 0e35e86592..5d4333c9bd 100644 --- a/src/render/renderer/renderer.rs +++ b/src/render/renderer/renderer.rs @@ -1,10 +1,12 @@ use crate::{ + asset::{AssetStorage, Handle}, legion::prelude::*, render::{ pipeline::PipelineDescriptor, render_resource::{ BufferInfo, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, }, + shader::Shader, texture::{SamplerDescriptor, TextureDescriptor}, }, }; @@ -40,6 +42,12 @@ pub trait Renderer { ); fn get_render_resources(&self) -> &RenderResources; fn get_render_resources_mut(&mut self) -> &mut RenderResources; + fn setup_render_pipeline( + &mut self, + pipeline_handle: Handle, + pipeline_descriptor: &mut PipelineDescriptor, + shader_storage: &AssetStorage, + ); fn setup_bind_groups( &mut self, render_resource_assignments: &mut RenderResourceAssignments, diff --git a/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs b/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs index 6febd890a9..f591317cc1 100644 --- a/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs +++ b/src/render/renderer/renderers/wgpu_renderer/wgpu_renderer.rs @@ -82,143 +82,10 @@ impl WgpuRenderer { self.intialized = true; } - pub fn create_render_pipeline( - &mut self, - pipeline_handle: Handle, - pipeline_descriptor: &mut PipelineDescriptor, - shader_storage: &AssetStorage, - ) { - let device = self.device.borrow(); - let layout = pipeline_descriptor.get_layout().unwrap(); - for bind_group in layout.bind_groups.iter() { - if let None = self.wgpu_resources.bind_group_layouts.get(&bind_group.id) { - let bind_group_layout_binding = bind_group - .bindings - .iter() - .map(|binding| wgpu::BindGroupLayoutEntry { - binding: binding.index, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: (&binding.bind_type).into(), - }) - .collect::>(); - let wgpu_bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: bind_group_layout_binding.as_slice(), - }); - - self.wgpu_resources - .bind_group_layouts - .insert(bind_group.id, wgpu_bind_group_layout); - } - } - - // setup and collect bind group layouts - let bind_group_layouts = layout - .bind_groups - .iter() - .map(|bind_group| { - self.wgpu_resources - .bind_group_layouts - .get(&bind_group.id) - .unwrap() - }) - .collect::>(); - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: bind_group_layouts.as_slice(), - }); - - let owned_vertex_buffer_descriptors = layout - .vertex_buffer_descriptors - .iter() - .map(|v| v.into()) - .collect::>(); - - let color_states = pipeline_descriptor - .color_states - .iter() - .map(|c| c.into()) - .collect::>(); - - if let None = self - .wgpu_resources - .shader_modules - .get(&pipeline_descriptor.shader_stages.vertex) - { - self.wgpu_resources.create_shader_module( - &device, - pipeline_descriptor.shader_stages.vertex, - shader_storage, - ); - } - - if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment { - if let None = self.wgpu_resources.shader_modules.get(&fragment_handle) { - self.wgpu_resources - .create_shader_module(&device, fragment_handle, shader_storage); - } - }; - - let vertex_shader_module = self - .wgpu_resources - .shader_modules - .get(&pipeline_descriptor.shader_stages.vertex) - .unwrap(); - - let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment { - Some(fragment_handle) => Some( - self.wgpu_resources - .shader_modules - .get(&fragment_handle) - .unwrap(), - ), - None => None, - }; - - let mut render_pipeline_descriptor = wgpu::RenderPipelineDescriptor { - layout: &pipeline_layout, - vertex_stage: wgpu::ProgrammableStageDescriptor { - module: &vertex_shader_module, - entry_point: "main", - }, - fragment_stage: match pipeline_descriptor.shader_stages.fragment { - Some(_) => Some(wgpu::ProgrammableStageDescriptor { - entry_point: "main", - module: fragment_shader_module.as_ref().unwrap(), - }), - None => None, - }, - rasterization_state: pipeline_descriptor - .rasterization_state - .as_ref() - .map(|r| r.into()), - primitive_topology: pipeline_descriptor.primitive_topology.into(), - color_states: &color_states, - depth_stencil_state: pipeline_descriptor - .depth_stencil_state - .as_ref() - .map(|d| d.into()), - vertex_state: wgpu::VertexStateDescriptor { - index_format: pipeline_descriptor.index_format.into(), - vertex_buffers: &owned_vertex_buffer_descriptors - .iter() - .map(|v| v.into()) - .collect::>(), - }, - sample_count: pipeline_descriptor.sample_count, - sample_mask: pipeline_descriptor.sample_mask, - alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled, - }; - - let render_pipeline = device.create_render_pipeline(&mut render_pipeline_descriptor); - self.render_pipelines - .insert(pipeline_handle, render_pipeline); - } - - pub fn create_render_pass<'a>( + pub fn create_render_pass<'a, 'b>( wgpu_resources: &'a WgpuResources, pass_descriptor: &PassDescriptor, - global_render_resource_assignments: &RenderResourceAssignments, + global_render_resource_assignments: &'b RenderResourceAssignments, encoder: &'a mut wgpu::CommandEncoder, primary_swap_chain: &Option, swap_chain_outputs: &'a HashMap, @@ -344,12 +211,13 @@ impl WgpuRenderer { } pub fn initialize_resource_providers(&mut self, world: &mut World, resources: &mut Resources) { - let mut render_graph = resources.get_mut::().unwrap(); self.encoder = Some( self.device .borrow() .create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }), ); + + let mut render_graph = resources.get_mut::().unwrap(); for resource_provider in render_graph.resource_providers.iter_mut() { resource_provider.initialize(self, world, resources); } @@ -491,68 +359,29 @@ impl Renderer for WgpuRenderer { let mut encoder = self.encoder.take().unwrap(); - let mut pipeline_storage = resources - .get_mut::>() - .unwrap(); - let shader_storage = resources.get::>().unwrap(); - let render_graph = resources.get::().unwrap(); - let mut render_graph_mut = resources.get_mut::().unwrap(); - let global_render_resource_assignments = - resources.get::().unwrap(); - let pipeline_compiler = resources.get::().unwrap(); - // setup draw targets - for (pass_name, _pass_descriptor) in render_graph.pass_descriptors.iter() { - if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) { - for pass_pipeline in pass_pipelines.iter() { - if let Some(compiled_pipelines_iter) = - pipeline_compiler.iter_compiled_pipelines(*pass_pipeline) - { - for compiled_pipeline_handle in compiled_pipelines_iter { - let compiled_pipeline_descriptor = - pipeline_storage.get_mut(compiled_pipeline_handle).unwrap(); - - // create wgpu pipeline if it doesn't exist - if !self.render_pipelines.contains_key(compiled_pipeline_handle) { - self.create_render_pipeline( - *compiled_pipeline_handle, - compiled_pipeline_descriptor, - &shader_storage, - ); - } - - // setup pipeline draw targets - for draw_target_name in compiled_pipeline_descriptor.draw_targets.iter() - { - let draw_target = render_graph_mut - .draw_targets - .get_mut(draw_target_name) - .unwrap(); - draw_target.setup( - world, - resources, - self, - *compiled_pipeline_handle, - ); - } - } - } - } - } - } + let mut render_graph = resources.get_mut::().unwrap(); + render_graph.setup_pipeline_draw_targets(world, resources, self); let (primary_swap_chain, swap_chain_outputs) = self.get_swap_chain_outputs(resources); // begin render passes + let pipeline_storage = resources.get::>().unwrap(); + let pipeline_compiler = resources.get::().unwrap(); + for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() { - let mut render_pass = Self::create_render_pass( - &self.wgpu_resources, - pass_descriptor, - &global_render_resource_assignments, - &mut encoder, - &primary_swap_chain, - &swap_chain_outputs, - ); + let mut render_pass = { + let global_render_resource_assignments = + resources.get::().unwrap(); + Self::create_render_pass( + &self.wgpu_resources, + pass_descriptor, + &global_render_resource_assignments, + &mut encoder, + &primary_swap_chain, + &swap_chain_outputs, + ) + }; if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) { for pass_pipeline in pass_pipelines.iter() { if let Some(compiled_pipelines_iter) = @@ -705,4 +534,141 @@ impl Renderer for WgpuRenderer { } } } + + fn setup_render_pipeline( + &mut self, + pipeline_handle: Handle, + pipeline_descriptor: &mut PipelineDescriptor, + shader_storage: &AssetStorage, + ) { + if self.render_pipelines.contains_key(&pipeline_handle) { + return; + } + + let device = self.device.borrow(); + let layout = pipeline_descriptor.get_layout().unwrap(); + for bind_group in layout.bind_groups.iter() { + if let None = self.wgpu_resources.bind_group_layouts.get(&bind_group.id) { + let bind_group_layout_binding = bind_group + .bindings + .iter() + .map(|binding| wgpu::BindGroupLayoutEntry { + binding: binding.index, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: (&binding.bind_type).into(), + }) + .collect::>(); + let wgpu_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + bindings: bind_group_layout_binding.as_slice(), + }); + + self.wgpu_resources + .bind_group_layouts + .insert(bind_group.id, wgpu_bind_group_layout); + } + } + + // setup and collect bind group layouts + let bind_group_layouts = layout + .bind_groups + .iter() + .map(|bind_group| { + self.wgpu_resources + .bind_group_layouts + .get(&bind_group.id) + .unwrap() + }) + .collect::>(); + + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + bind_group_layouts: bind_group_layouts.as_slice(), + }); + + let owned_vertex_buffer_descriptors = layout + .vertex_buffer_descriptors + .iter() + .map(|v| v.into()) + .collect::>(); + + let color_states = pipeline_descriptor + .color_states + .iter() + .map(|c| c.into()) + .collect::>(); + + if let None = self + .wgpu_resources + .shader_modules + .get(&pipeline_descriptor.shader_stages.vertex) + { + self.wgpu_resources.create_shader_module( + &device, + pipeline_descriptor.shader_stages.vertex, + shader_storage, + ); + } + + if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment { + if let None = self.wgpu_resources.shader_modules.get(&fragment_handle) { + self.wgpu_resources + .create_shader_module(&device, fragment_handle, shader_storage); + } + }; + + let vertex_shader_module = self + .wgpu_resources + .shader_modules + .get(&pipeline_descriptor.shader_stages.vertex) + .unwrap(); + + let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment { + Some(fragment_handle) => Some( + self.wgpu_resources + .shader_modules + .get(&fragment_handle) + .unwrap(), + ), + None => None, + }; + + let mut render_pipeline_descriptor = wgpu::RenderPipelineDescriptor { + layout: &pipeline_layout, + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: &vertex_shader_module, + entry_point: "main", + }, + fragment_stage: match pipeline_descriptor.shader_stages.fragment { + Some(_) => Some(wgpu::ProgrammableStageDescriptor { + entry_point: "main", + module: fragment_shader_module.as_ref().unwrap(), + }), + None => None, + }, + rasterization_state: pipeline_descriptor + .rasterization_state + .as_ref() + .map(|r| r.into()), + primitive_topology: pipeline_descriptor.primitive_topology.into(), + color_states: &color_states, + depth_stencil_state: pipeline_descriptor + .depth_stencil_state + .as_ref() + .map(|d| d.into()), + vertex_state: wgpu::VertexStateDescriptor { + index_format: pipeline_descriptor.index_format.into(), + vertex_buffers: &owned_vertex_buffer_descriptors + .iter() + .map(|v| v.into()) + .collect::>(), + }, + sample_count: pipeline_descriptor.sample_count, + sample_mask: pipeline_descriptor.sample_mask, + alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled, + }; + + let render_pipeline = device.create_render_pipeline(&mut render_pipeline_descriptor); + self.render_pipelines + .insert(pipeline_handle, render_pipeline); + } }