maplibre/render/resource/
pipeline.rs

1//! Utility for creating [RenderPipelines](wgpu::RenderPipeline)
2
3use std::borrow::Cow;
4
5use crate::render::resource::shader::{FragmentState, VertexState};
6
7pub trait RenderPipeline {
8    fn describe_render_pipeline(self) -> RenderPipelineDescriptor;
9}
10
11pub struct RenderPipelineDescriptor {
12    /// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.
13    pub label: Option<Cow<'static, str>>,
14    /// The layout of bind groups for this pipeline.
15    pub layout: Option<Vec<Vec<wgpu::BindGroupLayoutEntry>>>,
16    /// The compiled vertex stage, its entry point, and the input buffers layout.
17    pub vertex: VertexState,
18    /// The properties of the pipeline at the primitive assembly and rasterization level.
19    pub primitive: wgpu::PrimitiveState,
20    /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
21    pub depth_stencil: Option<wgpu::DepthStencilState>,
22    /// The multi-sampling properties of the pipeline.
23    pub multisample: wgpu::MultisampleState,
24    /// The compiled fragment stage, its entry point, and the color targets.
25    pub fragment: FragmentState,
26}
27
28impl RenderPipelineDescriptor {
29    pub fn initialize(&self, device: &wgpu::Device) -> wgpu::RenderPipeline {
30        let bind_group_layouts = if let Some(layout) = &self.layout {
31            layout
32                .iter()
33                .map(|entries| {
34                    device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
35                        label: None,
36                        entries: entries.as_ref(),
37                    })
38                })
39                .collect::<Vec<_>>()
40        } else {
41            vec![]
42        };
43
44        let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
45            bind_group_layouts: &bind_group_layouts.iter().collect::<Vec<_>>(),
46            ..Default::default()
47        });
48
49        let vertex_shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
50            label: None,
51            source: wgpu::ShaderSource::Wgsl(self.vertex.source.into()),
52        });
53        let fragment_shader_module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
54            label: None,
55            source: wgpu::ShaderSource::Wgsl(self.fragment.source.into()),
56        });
57
58        let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
59            label: self.label.as_ref().map(|label| label.as_ref()),
60            layout: Some(&pipeline_layout),
61            vertex: wgpu::VertexState {
62                module: &vertex_shader_module,
63                entry_point: self.vertex.entry_point,
64                compilation_options: Default::default(),
65                buffers: self
66                    .vertex
67                    .buffers
68                    .iter()
69                    .map(|layout| wgpu::VertexBufferLayout {
70                        array_stride: layout.array_stride,
71                        step_mode: layout.step_mode,
72                        attributes: layout.attributes.as_slice(),
73                    })
74                    .collect::<Vec<_>>()
75                    .as_slice(),
76            },
77            fragment: Some(wgpu::FragmentState {
78                module: &fragment_shader_module,
79                entry_point: self.fragment.entry_point,
80                compilation_options: Default::default(),
81                targets: self.fragment.targets.as_slice(),
82            }),
83            primitive: self.primitive,
84            depth_stencil: self.depth_stencil.clone(),
85            multisample: self.multisample,
86
87            multiview: None,
88            cache: None,
89        });
90
91        pipeline
92    }
93}