summaryrefslogtreecommitdiffstats
path: root/src/wgpuctx/pipeline.rs
blob: 760620361e9a0a53708d2259742a7a935ab46c61 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

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<wgpu::PipelineCompilationOptions<'a>>,
    fragment_comp_options: Option<wgpu::PipelineCompilationOptions<'a>>,

    vertex_buffer_layouts: Vec<wgpu::VertexBufferLayout<'a>>
}

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()
        }
    }

    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 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: wgpu::PrimitiveTopology::TriangleList,
                    strip_index_format: None,
                    front_face: wgpu::FrontFace::Ccw,
                    cull_mode: Some(wgpu::Face::Back),
                    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

            }
        )
    }
}