# tile_pipeline.rs - source
Source of the Rust file `maplibre/src/render/tile_pipeline.rs`.
Keywords: rust, rustlang, rust-lang

      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

    //! Utility for declaring pipelines.

    use crate::platform::MIN_BUFFER_SIZE;
    use crate::render::resource::{FragmentState, VertexState};
    use crate::render::resource::{RenderPipeline, RenderPipelineDescriptor};
    use crate::render::settings::Msaa;
    use crate::render::shaders::ShaderGlobals;
    use std::cmp;

    pub struct TilePipeline {
        bind_globals: bool,
        update_stencil: bool,
        debug_stencil: bool,
        wireframe: bool,
        msaa: Msaa,

        vertex_state: VertexState,
        fragment_state: FragmentState,
    }

    impl TilePipeline {
        pub(crate) fn new(
            msaa: Msaa,
            vertex_state: VertexState,
            fragment_state: FragmentState,
            bind_globals: bool,
            update_stencil: bool,
            debug_stencil: bool,
            wireframe: bool,
        ) -> Self {
            TilePipeline {
                bind_globals,
                update_stencil,
                debug_stencil,
                wireframe,
                msaa,
                vertex_state,
                fragment_state,
            }
        }
    }

    impl RenderPipeline for TilePipeline {
        fn describe_render_pipeline(self) -> RenderPipelineDescriptor {
            let stencil_state = if self.update_stencil {
                wgpu::StencilFaceState {
                    compare: wgpu::CompareFunction::Always, // Allow ALL values to update the stencil
                    fail_op: wgpu::StencilOperation::Keep,
                    depth_fail_op: wgpu::StencilOperation::Keep, // This is used when the depth test already failed
                    pass_op: wgpu::StencilOperation::Replace,
                }
            } else {
                wgpu::StencilFaceState {
                    compare: if self.debug_stencil {
                        wgpu::CompareFunction::Always
                    } else {
                        wgpu::CompareFunction::Equal
                    },
                    fail_op: wgpu::StencilOperation::Keep,
                    depth_fail_op: wgpu::StencilOperation::Keep,
                    pass_op: wgpu::StencilOperation::Keep,
                }
            };

            let globals_buffer_byte_size =
                cmp::max(MIN_BUFFER_SIZE, std::mem::size_of::<ShaderGlobals>() as u64);

            RenderPipelineDescriptor {
                label: None,
                layout: if self.bind_globals {
                    Some(vec![vec![wgpu::BindGroupLayoutEntry {
                        binding: 0,
                        visibility: wgpu::ShaderStages::VERTEX,
                        ty: wgpu::BindingType::Buffer {
                            ty: wgpu::BufferBindingType::Uniform,
                            has_dynamic_offset: false,
                            min_binding_size: wgpu::BufferSize::new(globals_buffer_byte_size),
                        },
                        count: None,
                    }]])
                } else {
                    None
                },
                vertex: self.vertex_state,
                fragment: self.fragment_state,
                primitive: wgpu::PrimitiveState {
                    topology: wgpu::PrimitiveTopology::TriangleList,
                    polygon_mode: if self.update_stencil {
                        wgpu::PolygonMode::Fill
                    } else if self.wireframe {
                        wgpu::PolygonMode::Line
                    } else {
                        wgpu::PolygonMode::Fill
                    },
                    front_face: wgpu::FrontFace::Ccw,
                    strip_index_format: None,
                    cull_mode: None, // Maps look the same from he bottom and above -> No culling needed
                    conservative: false,
                    unclipped_depth: false,
                },
                depth_stencil: Some(wgpu::DepthStencilState {
                    format: wgpu::TextureFormat::Depth24PlusStencil8,
                    depth_write_enabled: !self.update_stencil,
                    depth_compare: wgpu::CompareFunction::Greater,
                    stencil: wgpu::StencilState {
                        front: stencil_state,
                        back: stencil_state,
                        read_mask: 0xff, // Applied to stencil values being read from the stencil buffer
                        write_mask: 0xff, // Applied to fragment stencil values before being written to  the stencil buffer
                    },
                    bias: wgpu::DepthBiasState::default(),
                }),
                multisample: wgpu::MultisampleState {
                    count: self.msaa.samples,
                    mask: !0,
                    alpha_to_coverage_enabled: false,
                },
            }
        }
    }