use crate::wgpuctx::WgpuCtx; pub struct RenderPipelineBuilder<'a> { bind_groups: Vec<&'a wgpu::BindGroupLayout>, shader: &'a wgpu::ShaderModule, vertex_entry_point: Option<&'static str>, fragment_entry_point: Option<&'static str>, vertex_comp_options: Option>, fragment_comp_options: Option>, vertex_buffer_layouts: Vec>, cull_mode: Option, primitive_topology: wgpu::PrimitiveTopology } impl<'a> RenderPipelineBuilder<'a> { pub fn new( shader: &'a wgpu::ShaderModule) -> Self { Self { bind_groups: Vec::new(), shader: shader, vertex_entry_point: Some("vs_main"), fragment_entry_point: Some("fs_main"), vertex_comp_options: None, fragment_comp_options: None, vertex_buffer_layouts: Vec::new(), cull_mode: Some(wgpu::Face::Back), primitive_topology: wgpu::PrimitiveTopology::TriangleList } } pub fn add_bindgroup( mut self, bindgroup: &'a wgpu::BindGroupLayout) -> Self { self.bind_groups.push(bindgroup); self } pub fn add_vertex_layout( mut self, layout: wgpu::VertexBufferLayout<'a>) -> Self { self.vertex_buffer_layouts.push(layout); self } pub fn cull_mode( mut self, mode: Option ) -> Self { self.cull_mode = mode; self } pub fn primitive_topology( mut self, topology: wgpu::PrimitiveTopology ) -> Self { self.primitive_topology = topology; self } pub fn build( self, label: Option<&'static str>, wgpuctx: &WgpuCtx) -> wgpu::RenderPipeline { let layout_descr = wgpu::PipelineLayoutDescriptor { label: label, bind_group_layouts: self.bind_groups.as_slice(), push_constant_ranges: &[] }; let layout = wgpuctx.create_pipeline_layout(&layout_descr); wgpuctx.create_render_pipeline( &wgpu::RenderPipelineDescriptor { label: label, layout: Some(&layout), vertex: wgpu::VertexState { module: self.shader, entry_point: self.vertex_entry_point, compilation_options: match self.vertex_comp_options { Some(option) => option, None => wgpu::PipelineCompilationOptions::default() }, buffers: self.vertex_buffer_layouts.as_slice() }, fragment: Some(wgpu::FragmentState { module: self.shader, entry_point: self.fragment_entry_point, compilation_options: match self.fragment_comp_options { Some(option) => option, None => wgpu::PipelineCompilationOptions::default() }, targets: &[Some(wgpu::ColorTargetState { format: wgpuctx.surface_config().format, blend: Some(wgpu::BlendState{ color: wgpu::BlendComponent { src_factor: wgpu::BlendFactor::SrcAlpha, dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, operation: wgpu::BlendOperation::Add }, alpha: wgpu::BlendComponent::OVER }), write_mask: wgpu::ColorWrites::ALL })], }), primitive: wgpu::PrimitiveState { topology: self.primitive_topology, strip_index_format: if self.primitive_topology.is_strip() { Some(wgpu::IndexFormat::Uint32) } else { None }, front_face: wgpu::FrontFace::Ccw, cull_mode: self.cull_mode, polygon_mode: wgpu::PolygonMode::Fill, unclipped_depth: false, conservative: false }, depth_stencil: None, multisample: wgpu::MultisampleState { count: 1, mask: !0, alpha_to_coverage_enabled: false }, multiview: None, cache: None } ) } }