From d9bd2d4f152ec1e0614489ddfe475b9f7abd01d7 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Fri, 17 Jan 2020 18:54:05 -0800 Subject: [PATCH] pipeline builder --- src/render/render_graph_2/mod.rs | 60 +++++++++---- src/render/render_graph_2/pipeline.rs | 125 ++++++++++++++++++++++++-- src/render/shader.rs | 9 ++ 3 files changed, 169 insertions(+), 25 deletions(-) diff --git a/src/render/render_graph_2/mod.rs b/src/render/render_graph_2/mod.rs index 53d6b1a3fa..8c005fbe76 100644 --- a/src/render/render_graph_2/mod.rs +++ b/src/render/render_graph_2/mod.rs @@ -2,14 +2,15 @@ mod pipeline; pub use pipeline::*; +use crate::prelude::*; use crate::{asset::Texture, legion::{prelude::{Entity, World}, borrow::{Ref, RefMap}}, render::Albedo}; -use std::{collections::{HashMap, HashSet}, ops::Deref}; +use std::collections::HashMap; pub enum ShaderValue<'a> { Int(u32), Float(f32), - Vec4(crate::math::Vec4), - Texture(&'a crate::asset::Handle), + Vec4(Vec4), + Texture(&'a Handle), } type ShaderMaterialSelector = fn(Entity, &World) -> Option>; @@ -88,12 +89,20 @@ enum ResourceType { // updates resources based on events like "resize" or "update" // if there are no resources in use, dont run allocate resource provider resources on gpu trait ResourceProvider { - fn get_resources() -> Vec; + fn get_resources(&self) -> &[Resource]; } // holds on to passes, pipeline descriptions, instances // passes: shadow, forward -struct RenderGraph; +struct RenderGraph { + pipeline_definitions: HashMap, + pipeline_instances: HashMap, +} + +struct RenderGraphBuilder { + +} + /* RenderGraph::build() .AddPass("forward", Pass { @@ -127,20 +136,35 @@ RenderGraph::build() ) */ -// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc -// Mesh target -trait DrawTarget { - fn draw(device: &wgpu::Device); +pub struct RenderPassColorAttachmentDescription { + /// The actual color attachment. + pub attachment: String, + + /// The resolve target for this color attachment, if any. + pub resolve_target: Option, + + /// The beginning-of-pass load operation for this color attachment. + pub load_op: wgpu::LoadOp, + + /// The end-of-pass store operation for this color attachment. + pub store_op: wgpu::StoreOp, + + /// The color that will be assigned to every pixel of this attachment when cleared. + pub clear_color: wgpu::Color, } -// a texture that is rendered to. TextureView or SwapChain -struct RenderTarget; +pub struct RenderPassDepthStencilAttachmentDescription { + pub attachment: String, + pub depth_load_op: wgpu::LoadOp, + pub depth_store_op: wgpu::StoreOp, + pub clear_depth: f32, + pub stencil_load_op: wgpu::LoadOp, + pub stencil_store_op: wgpu::StoreOp, + pub clear_stencil: u32, +} // A set of pipeline bindings and draw calls with color and depth outputs -struct Pass; - -// A pipeline description (original shaders) -struct PipelineDefinition; - -// A specific instance of a pipeline definition -struct Pipeline; \ No newline at end of file +struct Pass { + color_attachments: Vec, + depth_stencil_attachment: Option, +} \ No newline at end of file diff --git a/src/render/render_graph_2/pipeline.rs b/src/render/render_graph_2/pipeline.rs index fc2a1bfc98..6907c6b569 100644 --- a/src/render/render_graph_2/pipeline.rs +++ b/src/render/render_graph_2/pipeline.rs @@ -1,4 +1,14 @@ -use crate::render::shader::ShaderStages; +use crate::{ + legion::prelude::World, + render::shader::{Shader, ShaderStages}, +}; + +// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc +// Mesh target +// trait DrawTarget { +// fn draw(device: &wgpu::Device); +// } +type DrawTarget = fn(world: &World, device: &wgpu::Device); pub struct VertexBufferDefinition { pub stride: wgpu::BufferAddress, @@ -17,6 +27,7 @@ impl<'a> Into> for &'a VertexBufferDefinition { } pub struct PipelineDefinition { + pub draw_targets: Vec, pub shader_stages: ShaderStages, pub rasterization_state: Option, @@ -49,6 +60,30 @@ pub struct PipelineDefinition { pub alpha_to_coverage_enabled: bool, } +impl PipelineDefinition { + fn new(vertex_shader: Shader) -> Self { + PipelineDefinition { + color_states: Vec::new(), + depth_stencil_state: None, + draw_targets: Vec::new(), + shader_stages: ShaderStages::new(vertex_shader), + vertex_buffer_definitions: Vec::new(), + 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, + index_format: wgpu::IndexFormat::Uint16, + sample_count: 1, + sample_mask: !0, + alpha_to_coverage_enabled: false, + } + } +} + impl PipelineDefinition { pub fn create_render_pipeline(&self, device: &wgpu::Device) -> wgpu::RenderPipeline { let vertex_shader_module = self.shader_stages.vertex.create_shader_module(device); @@ -57,11 +92,9 @@ impl PipelineDefinition { None => None, }; - let pipeline_layout = - device - .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: &[], - }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + bind_group_layouts: &[], + }); let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor { layout: &pipeline_layout, vertex_stage: wgpu::ProgrammableStageDescriptor { @@ -80,7 +113,11 @@ impl PipelineDefinition { color_states: &self.color_states, depth_stencil_state: self.depth_stencil_state.clone(), index_format: self.index_format, - vertex_buffers: &self.vertex_buffer_definitions.iter().map(|v| v.into()).collect::>(), + vertex_buffers: &self + .vertex_buffer_definitions + .iter() + .map(|v| v.into()) + .collect::>(), sample_count: self.sample_count, sample_mask: self.sample_mask, alpha_to_coverage_enabled: self.alpha_to_coverage_enabled, @@ -88,4 +125,78 @@ impl PipelineDefinition { device.create_render_pipeline(&render_pipeline_descriptor) } + + pub fn build(vertex_shader: Shader) -> PipelineBuilder { + PipelineBuilder::new(vertex_shader) + } +} + +pub struct PipelineBuilder { + pipeline: PipelineDefinition, +} + +impl PipelineBuilder { + pub fn new(vertex_shader: Shader) -> Self { + PipelineBuilder { + pipeline: PipelineDefinition::new(vertex_shader), + } + } + + pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self { + self.pipeline.shader_stages.fragment = Some(fragment_shader); + self + } + + pub fn with_color_state(mut self, color_state_descriptor: wgpu::ColorStateDescriptor) -> Self { + self.pipeline.color_states.push(color_state_descriptor); + self + } + + pub fn with_depth_stencil_state(mut self, depth_stencil_state: wgpu::DepthStencilStateDescriptor) -> Self { + if let Some(_) = self.pipeline.depth_stencil_state { + panic!("Depth stencil state has already been set"); + } + self.pipeline.depth_stencil_state = Some(depth_stencil_state); + self + } + + pub fn with_vertex_buffer_definition(mut self, vertex_buffer_definition: VertexBufferDefinition) -> Self { + self.pipeline.vertex_buffer_definitions.push(vertex_buffer_definition); + self + } + + pub fn with_index_format(mut self, index_format: wgpu::IndexFormat) -> Self { + self.pipeline.index_format = index_format; + self + } + + pub fn with_draw_target(mut self, draw_target: DrawTarget) -> Self { + self.pipeline.draw_targets.push(draw_target); + self + } + + pub fn with_rasterization_state(mut self, rasterization_state: wgpu::RasterizationStateDescriptor) -> Self { + self.pipeline.rasterization_state = Some(rasterization_state); + self + } + + pub fn with_primitive_topology(mut self, primitive_topology: wgpu::PrimitiveTopology) -> Self { + self.pipeline.primitive_topology = primitive_topology; + self + } + + pub fn with_sample_count(mut self, sample_count: u32) -> Self { + self.pipeline.sample_count = sample_count; + self + } + + pub fn with_alpha_to_coverage_enabled(mut self, alpha_to_coverage_enabled: bool) -> Self { + self.pipeline.alpha_to_coverage_enabled = alpha_to_coverage_enabled; + self + } + + pub fn with_sample_mask(mut self, sample_mask: u32) -> Self { + self.pipeline.sample_mask = sample_mask; + self + } } diff --git a/src/render/shader.rs b/src/render/shader.rs index 0cc1fe35be..168299ac2a 100644 --- a/src/render/shader.rs +++ b/src/render/shader.rs @@ -65,4 +65,13 @@ impl Shader { pub struct ShaderStages { pub vertex: Shader, pub fragment: Option, +} + +impl ShaderStages { + pub fn new(vertex_shader: Shader) -> Self { + ShaderStages { + vertex: vertex_shader, + fragment: None, + } + } } \ No newline at end of file