# render_commands.rs - source
Source of the Rust file `maplibre/src/vector/render_commands.rs`.

    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

    //! Specifies the instructions which are going to be sent to the GPU. Render commands can be concatenated
    //! into a new render command which executes multiple instruction sets.
    use crate::{
        render::{
            eventually::{Eventually, Eventually::Initialized},
            render_phase::{LayerItem, PhaseItem, RenderCommand, RenderCommandResult},
            resource::TrackedRenderPass,
            tile_view_pattern::WgpuTileViewPattern,
            INDEX_FORMAT,
        },
        tcs::world::World,
        vector::{VectorBufferPool, VectorPipeline},
    };

    pub struct SetVectorTilePipeline;
    impl<P: PhaseItem> RenderCommand<P> for SetVectorTilePipeline {
        fn render<'w>(
            world: &'w World,
            _item: &P,
            pass: &mut TrackedRenderPass<'w>,
        ) -> RenderCommandResult {
            let Some(Initialized(pipeline)) = world.resources.get::<Eventually<VectorPipeline>>()
            else {
                return RenderCommandResult::Failure;
            };

            pass.set_render_pipeline(pipeline);
            RenderCommandResult::Success
        }
    }

    pub struct DrawVectorTile;
    impl RenderCommand<LayerItem> for DrawVectorTile {
        fn render<'w>(
            world: &'w World,
            item: &LayerItem,
            pass: &mut TrackedRenderPass<'w>,
        ) -> RenderCommandResult {
            let Some((Initialized(buffer_pool), Initialized(tile_view_pattern))) =
                world.resources.query::<(
                    &Eventually<VectorBufferPool>,
                    &Eventually<WgpuTileViewPattern>,
                )>()
            else {
                return RenderCommandResult::Failure;
            };

            let Some(vector_layers) = buffer_pool.index().get_layers(item.tile.coords) else {
                return RenderCommandResult::Failure;
            };

            let Some(entry) = vector_layers
                .iter()
                .find(|entry| entry.style_layer.id == item.style_layer)
            else {
                return RenderCommandResult::Failure;
            };

            let source_shape = &item.source_shape;

            // Uses stencil value of requested tile and the shape of the requested tile
            let reference = source_shape.coords().stencil_reference_value_3d() as u32;

            tracing::trace!(
                "Drawing layer {:?} at {}",
                entry.style_layer.source_layer,
                entry.coords
            );

            let index_range = entry.indices_buffer_range();

            if index_range.is_empty() {
                tracing::error!("Tried to draw a vector tile without any vertices");
                return RenderCommandResult::Failure;
            }

            pass.set_stencil_reference(reference);

            pass.set_index_buffer(buffer_pool.indices().slice(index_range), INDEX_FORMAT);
            pass.set_vertex_buffer(
                0,
                buffer_pool.vertices().slice(entry.vertices_buffer_range()),
            );
            let tile_view_pattern_buffer = source_shape
                .buffer_range()
                .expect("tile_view_pattern needs to be uploaded first"); // FIXME tcs
            pass.set_vertex_buffer(
                1,
                tile_view_pattern.buffer().slice(tile_view_pattern_buffer),
            );
            pass.set_vertex_buffer(
                2,
                buffer_pool
                    .metadata()
                    .slice(entry.layer_metadata_buffer_range()),
            );
            pass.set_vertex_buffer(
                3,
                buffer_pool
                    .feature_metadata()
                    .slice(entry.feature_metadata_buffer_range()),
            );
            pass.draw_indexed(entry.indices_range(), 0, 0..1);

            RenderCommandResult::Success
        }
    }

    pub type DrawVectorTiles = (SetVectorTilePipeline, DrawVectorTile);