From aa16023f4166a05bda78683e747fb90d1f95d451 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Wed, 1 Jan 2020 14:23:39 -0600 Subject: [PATCH] port forward-instanced to RenderGraph --- src/application.rs | 12 +- src/render/forward/mod.rs | 25 +- src/render/forward_instanced/mod.rs | 373 ++++++++++++---------------- src/render/mod.rs | 25 +- 4 files changed, 190 insertions(+), 245 deletions(-) diff --git a/src/application.rs b/src/application.rs index a45a87fa00..6bf1d7ab33 100644 --- a/src/application.rs +++ b/src/application.rs @@ -35,16 +35,10 @@ impl Application { self.render_graph.data.set_bind_group_layout("local", local_bind_group_layout); - // let shadow_pass = ShadowPass::new(&mut self.device, &mut self.world, &self.render_resources, vertex_buffer_descriptor.clone()); - // let forward_shadow_pass = ForwardShadowPass::new(&mut self.device, &self.world, &self.render_resources, &shadow_pass, vertex_buffer_descriptor.clone(), &self.swap_chain_descriptor); - // let forward_pass = ForwardPass::new(&mut self.device, &self.world, &self.render_resources, vertex_buffer_descriptor.clone(), &self.swap_chain_descriptor); - // let forward_instanced_pass = ForwardInstancedPass::new(&mut self.device, &self.world, &self.render_resources, vertex_buffer_descriptor, &self.swap_chain_descriptor); - // self.render_passes.push(Box::new(shadow_pass)); - // self.render_passes.push(Box::new(forward_shadow_pass)); - // self.render_passes.push(Box::new(forward_pass)); - // self.render_passes.push(Box::new(forward_instanced_pass)); - self.render_graph.set_pass("forward", Box::new(ForwardPass::new())); + let depth_format = wgpu::TextureFormat::Depth32Float; + self.render_graph.set_pass("forward", Box::new(ForwardPass::new(depth_format))); self.render_graph.set_pipeline("forward", Box::new(ForwardPipelineNew::new())); + self.render_graph.set_pipeline("forward_instanced", Box::new(ForwardInstancedPipeline::new(depth_format))); } fn update(&mut self) { diff --git a/src/render/forward/mod.rs b/src/render/forward/mod.rs index f7c812909d..4fa84f886e 100644 --- a/src/render/forward/mod.rs +++ b/src/render/forward/mod.rs @@ -1,6 +1,5 @@ -use crate::{render::*, asset::*, render::mesh::*, vertex::Vertex}; +use crate::{render::*, asset::*, render::mesh::*}; use legion::prelude::*; -use std::mem; use zerocopy::{AsBytes, FromBytes}; use wgpu::{Device, SwapChainDescriptor, SwapChainOutput}; @@ -22,9 +21,9 @@ pub struct ForwardPass { } impl ForwardPass { - pub fn new() -> Self { + pub fn new(depth_format: wgpu::TextureFormat) -> Self { ForwardPass { - depth_format: wgpu::TextureFormat::Depth32Float + depth_format, } } fn get_depth_texture(&self, device: &Device, swap_chain_descriptor: &SwapChainDescriptor) -> wgpu::TextureView { @@ -150,23 +149,7 @@ impl PipelineNew for ForwardPipelineNew { bind_group_layouts: &[&bind_group_layout, local_bind_group_layout], }); - let vertex_size = mem::size_of::(); - let vertex_buffer_descriptor = wgpu::VertexBufferDescriptor { - stride: vertex_size as wgpu::BufferAddress, - step_mode: wgpu::InputStepMode::Vertex, - attributes: &[ - wgpu::VertexAttributeDescriptor { - format: wgpu::VertexFormat::Float4, - offset: 0, - shader_location: 0, - }, - wgpu::VertexAttributeDescriptor { - format: wgpu::VertexFormat::Float4, - offset: 4 * 4, - shader_location: 1, - }, - ], - }; + let vertex_buffer_descriptor = get_vertex_buffer_descriptor(); let vs_module = render_graph.device.create_shader_module(&vs_bytes); let fs_module = render_graph.device.create_shader_module(&fs_bytes); diff --git a/src/render/forward_instanced/mod.rs b/src/render/forward_instanced/mod.rs index 9b44045db9..1d9bf674ad 100644 --- a/src/render/forward_instanced/mod.rs +++ b/src/render/forward_instanced/mod.rs @@ -1,9 +1,8 @@ -use crate::{render::*, asset::*, render::mesh::*, math, LocalToWorld}; +use crate::{render::*, asset::*, render::mesh::*, LocalToWorld}; use legion::prelude::*; use std::mem; use zerocopy::AsBytes; -use wgpu::{Buffer, CommandEncoder, Device, VertexBufferDescriptor, SwapChainDescriptor, SwapChainOutput}; - +use wgpu::{Device, SwapChainOutput}; pub struct InstanceBufferInfo { pub buffer: wgpu::Buffer, @@ -11,201 +10,20 @@ pub struct InstanceBufferInfo { pub mesh_id: usize, } -pub struct ForwardInstancedPass { - pub pipeline: wgpu::RenderPipeline, - pub bind_group: wgpu::BindGroup, - pub forward_uniform_buffer: wgpu::Buffer, - pub depth_texture: wgpu::TextureView, - pub instance_buffer_infos: Vec, +pub struct ForwardInstancedPipeline { + pub pipeline: Option, + pub depth_format: wgpu::TextureFormat, + pub local_bind_group: Option, + pub instance_buffer_infos: Option>, } -impl Pipeline for ForwardInstancedPass { - fn render(&mut self, device: &Device, frame: &SwapChainOutput, encoder: &mut CommandEncoder, world: &mut World, _: &RenderResources) { - self.instance_buffer_infos = ForwardInstancedPass::create_instance_buffer_infos(device, world); - let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &frame.view, - resolve_target: None, - load_op: wgpu::LoadOp::Clear, - store_op: wgpu::StoreOp::Store, - clear_color: wgpu::Color { - r: 0.3, - g: 0.4, - b: 0.5, - a: 1.0, - }, - }], - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { - attachment: &self.depth_texture, - depth_load_op: wgpu::LoadOp::Clear, - depth_store_op: wgpu::StoreOp::Store, - stencil_load_op: wgpu::LoadOp::Clear, - stencil_store_op: wgpu::StoreOp::Store, - clear_depth: 1.0, - clear_stencil: 0, - }), - }); - pass.set_pipeline(&self.pipeline); - pass.set_bind_group(0, &self.bind_group, &[]); - - let mut mesh_storage = world.resources.get_mut::>().unwrap(); - for instance_buffer_info in self.instance_buffer_infos.iter() { - if let Some(mesh_asset) = mesh_storage.get(instance_buffer_info.mesh_id) { - mesh_asset.setup_buffers(device); - pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); - pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); - pass.set_vertex_buffers(1, &[(&instance_buffer_info.buffer, 0)]); - pass.draw_indexed(0 .. mesh_asset.indices.len() as u32, 0, 0 .. instance_buffer_info.instance_count as u32); - }; - } - } - - fn resize(&mut self, device: &Device, frame: &SwapChainDescriptor) { - self.depth_texture = Self::get_depth_texture(device, frame); - } - - fn get_camera_uniform_buffer(&self) -> Option<&Buffer> { - Some(&self.forward_uniform_buffer) - } -} - -impl ForwardInstancedPass { - pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; - - pub fn new(device: &Device, world: &World, render_resources: &RenderResources, vertex_buffer_descriptor: VertexBufferDescriptor, swap_chain_descriptor: &SwapChainDescriptor) -> Self { - let vs_bytes = shader::load_glsl( - include_str!("forward_instanced.vert"), - shader::ShaderStage::Vertex, - ); - let fs_bytes = shader::load_glsl( - include_str!("forward_instanced.frag"), - shader::ShaderStage::Fragment, - ); - - let bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: &[ - wgpu::BindGroupLayoutBinding { - binding: 0, // global - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { dynamic: false }, - }, - wgpu::BindGroupLayoutBinding { - binding: 1, // lights - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { dynamic: false }, - } - ], - }); - - let light_count = >::query().iter_immutable(world).count(); - let forward_uniforms = ForwardUniforms { - proj: math::Mat4::identity().to_cols_array_2d(), - num_lights: [light_count as u32, 0, 0, 0], - }; - - let uniform_size = mem::size_of::() as wgpu::BufferAddress; - let forward_uniform_buffer = device.create_buffer_with_data( - forward_uniforms.as_bytes(), - wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - ); - - // Create bind group - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &bind_group_layout, - bindings: &[ - wgpu::Binding { - binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &forward_uniform_buffer, - range: 0 .. uniform_size, - }, - }, - wgpu::Binding { - binding: 1, - resource: wgpu::BindingResource::Buffer { - buffer: &render_resources.light_uniform_buffer.buffer, - range: 0 .. render_resources.light_uniform_buffer.size, - }, - } - ], - }); - - let simple_material_uniforms_size = mem::size_of::(); - let instance_buffer_descriptor = wgpu::VertexBufferDescriptor { - stride: simple_material_uniforms_size as wgpu::BufferAddress, - step_mode: wgpu::InputStepMode::Instance, - attributes: &[ - wgpu::VertexAttributeDescriptor { - format: wgpu::VertexFormat::Float3, - offset: 0, - shader_location: 2, - }, - wgpu::VertexAttributeDescriptor { - format: wgpu::VertexFormat::Float4, - offset: 3 * 4, - shader_location: 3, - }, - ], - }; - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: &[&bind_group_layout], - }); - - let vs_module = device.create_shader_module(&vs_bytes); - let fs_module = device.create_shader_module(&fs_bytes); - - let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - layout: &pipeline_layout, - vertex_stage: wgpu::ProgrammableStageDescriptor { - module: &vs_module, - entry_point: "main", - }, - fragment_stage: Some(wgpu::ProgrammableStageDescriptor { - module: &fs_module, - entry_point: "main", - }), - rasterization_state: Some(wgpu::RasterizationStateDescriptor { - front_face: wgpu::FrontFace::Ccw, - cull_mode: wgpu::CullMode::Back, - depth_bias: 0, - depth_bias_slope_scale: 0.0, - depth_bias_clamp: 0.0, - }), - primitive_topology: wgpu::PrimitiveTopology::TriangleList, - color_states: &[ - wgpu::ColorStateDescriptor { - format: swap_chain_descriptor.format, - color_blend: wgpu::BlendDescriptor::REPLACE, - alpha_blend: wgpu::BlendDescriptor::REPLACE, - write_mask: wgpu::ColorWrite::ALL, - }, - ], - depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { - format: Self::DEPTH_FORMAT, - depth_write_enabled: true, - depth_compare: wgpu::CompareFunction::Less, - stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE, - stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE, - stencil_read_mask: 0, - stencil_write_mask: 0, - }), - index_format: wgpu::IndexFormat::Uint16, - vertex_buffers: &[vertex_buffer_descriptor, instance_buffer_descriptor], - sample_count: 1, - sample_mask: !0, - alpha_to_coverage_enabled: false, - }); - - let instance_buffer_infos = ForwardInstancedPass::create_instance_buffer_infos(device, world); - - ForwardInstancedPass { - pipeline, - bind_group, - forward_uniform_buffer, - depth_texture: Self::get_depth_texture(device, swap_chain_descriptor), - instance_buffer_infos +impl ForwardInstancedPipeline { + pub fn new(depth_format: wgpu::TextureFormat) -> Self { + ForwardInstancedPipeline { + pipeline: None, + depth_format, + local_bind_group: None, + instance_buffer_infos: None, } } @@ -277,23 +95,150 @@ impl ForwardInstancedPass { instance_buffer_infos } - - fn get_depth_texture(device: &Device, swap_chain_descriptor: &SwapChainDescriptor) -> wgpu::TextureView { - let texture = device.create_texture(&wgpu::TextureDescriptor { - size: wgpu::Extent3d { - width: swap_chain_descriptor.width, - height: swap_chain_descriptor.height, - depth: 1, - }, - array_layer_count: 1, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: Self::DEPTH_FORMAT, - usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, - }); - - texture.create_default_view() - } } +impl PipelineNew for ForwardInstancedPipeline { + fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World) { + let vs_bytes = shader::load_glsl( + include_str!("forward_instanced.vert"), + shader::ShaderStage::Vertex, + ); + let fs_bytes = shader::load_glsl( + include_str!("forward_instanced.frag"), + shader::ShaderStage::Fragment, + ); + + let bind_group_layout = + render_graph.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + bindings: &[ + wgpu::BindGroupLayoutBinding { + binding: 0, // global + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, + }, + wgpu::BindGroupLayoutBinding { + binding: 1, // lights + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, + } + ], + }); + + // TODO: this is the same as normal forward pipeline. we can probably reuse + self.local_bind_group = Some({ + + let forward_uniform_buffer = render_graph.get_uniform_buffer(render_resources::FORWARD_UNIFORM_BUFFER_NAME).unwrap(); + let light_uniform_buffer = render_graph.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME).unwrap(); + + // Create bind group + render_graph.device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &bind_group_layout, + bindings: &[ + wgpu::Binding { + binding: 0, + resource: forward_uniform_buffer.get_binding_resource(), + }, + wgpu::Binding { + binding: 1, + resource: light_uniform_buffer.get_binding_resource(), + } + ], + }) + }); + + let simple_material_uniforms_size = mem::size_of::(); + let instance_buffer_descriptor = wgpu::VertexBufferDescriptor { + stride: simple_material_uniforms_size as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Instance, + attributes: &[ + wgpu::VertexAttributeDescriptor { + format: wgpu::VertexFormat::Float3, + offset: 0, + shader_location: 2, + }, + wgpu::VertexAttributeDescriptor { + format: wgpu::VertexFormat::Float4, + offset: 3 * 4, + shader_location: 3, + }, + ], + }; + + let vertex_buffer_descriptor = get_vertex_buffer_descriptor(); + + let pipeline_layout = render_graph.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + bind_group_layouts: &[&bind_group_layout], + }); + + let vs_module = render_graph.device.create_shader_module(&vs_bytes); + let fs_module = render_graph.device.create_shader_module(&fs_bytes); + + self.pipeline = Some(render_graph.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + layout: &pipeline_layout, + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: &vs_module, + entry_point: "main", + }, + fragment_stage: Some(wgpu::ProgrammableStageDescriptor { + module: &fs_module, + entry_point: "main", + }), + rasterization_state: Some(wgpu::RasterizationStateDescriptor { + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + depth_bias: 0, + depth_bias_slope_scale: 0.0, + depth_bias_clamp: 0.0, + }), + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + color_states: &[ + wgpu::ColorStateDescriptor { + format: render_graph.swap_chain_descriptor.format, + color_blend: wgpu::BlendDescriptor::REPLACE, + alpha_blend: wgpu::BlendDescriptor::REPLACE, + write_mask: wgpu::ColorWrite::ALL, + }, + ], + depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor { + format: self.depth_format, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::Less, + stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE, + stencil_read_mask: 0, + stencil_write_mask: 0, + }), + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[vertex_buffer_descriptor, instance_buffer_descriptor], + sample_count: 1, + sample_mask: !0, + alpha_to_coverage_enabled: false, + })); + + self.instance_buffer_infos = Some(Self::create_instance_buffer_infos(&render_graph.device, world)); + } + + fn render(&mut self, render_graph: &RenderGraphData, pass: &mut wgpu::RenderPass, frame: &SwapChainOutput, world: &mut World) { + self.instance_buffer_infos = Some(Self::create_instance_buffer_infos(&render_graph.device, world)); + pass.set_bind_group(0, self.local_bind_group.as_ref().unwrap(), &[]); + + let mut mesh_storage = world.resources.get_mut::>().unwrap(); + for instance_buffer_info in self.instance_buffer_infos.as_ref().unwrap().iter() { + if let Some(mesh_asset) = mesh_storage.get(instance_buffer_info.mesh_id) { + mesh_asset.setup_buffers(&render_graph.device); + pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); + pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); + pass.set_vertex_buffers(1, &[(&instance_buffer_info.buffer, 0)]); + pass.draw_indexed(0 .. mesh_asset.indices.len() as u32, 0, 0 .. instance_buffer_info.instance_count as u32); + }; + } + } + + fn resize(&mut self, render_graph: &RenderGraphData) { + + } + + fn get_pipeline(&self) -> &wgpu::RenderPipeline { + self.pipeline.as_ref().unwrap() + } +} \ No newline at end of file diff --git a/src/render/mod.rs b/src/render/mod.rs index ead6e6210d..a782a42228 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -13,7 +13,7 @@ mod material; pub use forward::{ForwardUniforms, ForwardPipelineNew, ForwardPass}; pub use forward_shadow::{ForwardShadowPass}; -pub use forward_instanced::ForwardInstancedPass; +pub use forward_instanced::ForwardInstancedPipeline; pub use shadow::ShadowPass; pub use light::*; pub use shader::*; @@ -24,6 +24,9 @@ pub use mesh::*; pub use camera::*; pub use render_resources::RenderResources; +use std::mem; +use crate::vertex::Vertex; + pub struct UniformBuffer { pub buffer: wgpu::Buffer, pub size: u64, @@ -36,4 +39,24 @@ impl UniformBuffer { range: 0 .. self.size, } } +} + +pub fn get_vertex_buffer_descriptor<'a>() -> wgpu::VertexBufferDescriptor<'a> { + let vertex_size = mem::size_of::(); + wgpu::VertexBufferDescriptor { + stride: vertex_size as wgpu::BufferAddress, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &[ + wgpu::VertexAttributeDescriptor { + format: wgpu::VertexFormat::Float4, + offset: 0, + shader_location: 0, + }, + wgpu::VertexAttributeDescriptor { + format: wgpu::VertexFormat::Float4, + offset: 4 * 4, + shader_location: 1, + }, + ], + } } \ No newline at end of file