maplibre/vector/
render_commands.rs1use crate::{
4 render::{
5 eventually::{Eventually, Eventually::Initialized},
6 render_phase::{LayerItem, PhaseItem, RenderCommand, RenderCommandResult},
7 resource::TrackedRenderPass,
8 tile_view_pattern::WgpuTileViewPattern,
9 INDEX_FORMAT,
10 },
11 tcs::world::World,
12 vector::{LinePipeline, VectorBufferPool, VectorPipeline},
13};
14
15pub struct SetVectorTilePipeline;
16impl<P: PhaseItem> RenderCommand<P> for SetVectorTilePipeline {
17 fn render<'w>(
18 world: &'w World,
19 _item: &P,
20 pass: &mut TrackedRenderPass<'w>,
21 ) -> RenderCommandResult {
22 let Some(Initialized(pipeline)) = world.resources.get::<Eventually<VectorPipeline>>()
23 else {
24 return RenderCommandResult::Failure;
25 };
26
27 pass.set_render_pipeline(pipeline);
28 RenderCommandResult::Success
29 }
30}
31
32pub struct DrawVectorTile;
33impl RenderCommand<LayerItem> for DrawVectorTile {
34 fn render<'w>(
35 world: &'w World,
36 item: &LayerItem,
37 pass: &mut TrackedRenderPass<'w>,
38 ) -> RenderCommandResult {
39 let Some((Initialized(buffer_pool), Initialized(tile_view_pattern))) =
40 world.resources.query::<(
41 &Eventually<VectorBufferPool>,
42 &Eventually<WgpuTileViewPattern>,
43 )>()
44 else {
45 return RenderCommandResult::Failure;
46 };
47
48 let Some(vector_layers) = buffer_pool.index().get_layers(item.tile.coords) else {
49 return RenderCommandResult::Failure;
50 };
51
52 let Some(entry) = vector_layers
53 .iter()
54 .find(|entry| entry.style_layer.id == item.style_layer)
55 else {
56 return RenderCommandResult::Failure;
57 };
58
59 let source_shape = &item.source_shape;
60
61 let reference = source_shape.coords().stencil_reference_value_3d() as u32;
63
64 tracing::trace!(
65 "Drawing layer {:?} at {}",
66 entry.style_layer.source_layer,
67 entry.coords
68 );
69
70 let index_range = entry.indices_buffer_range();
71
72 if index_range.is_empty() {
73 tracing::error!("Tried to draw a vector tile without any vertices");
74 return RenderCommandResult::Failure;
75 }
76
77 pass.set_stencil_reference(reference);
78
79 pass.set_index_buffer(buffer_pool.indices().slice(index_range), INDEX_FORMAT);
80 pass.set_vertex_buffer(
81 0,
82 buffer_pool.vertices().slice(entry.vertices_buffer_range()),
83 );
84 let tile_view_pattern_buffer = source_shape
85 .buffer_range()
86 .expect("tile_view_pattern needs to be uploaded first"); pass.set_vertex_buffer(
88 1,
89 tile_view_pattern.buffer().slice(tile_view_pattern_buffer),
90 );
91 pass.set_vertex_buffer(
92 2,
93 buffer_pool
94 .metadata()
95 .slice(entry.layer_metadata_buffer_range()),
96 );
97 pass.set_vertex_buffer(
98 3,
99 buffer_pool
100 .feature_metadata()
101 .slice(entry.feature_metadata_buffer_range()),
102 );
103 pass.draw_indexed(entry.indices_range(), 0, 0..1);
104
105 RenderCommandResult::Success
106 }
107}
108
109pub struct SetLineTilePipeline;
110impl<P: PhaseItem> RenderCommand<P> for SetLineTilePipeline {
111 fn render<'w>(
112 world: &'w World,
113 _item: &P,
114 pass: &mut TrackedRenderPass<'w>,
115 ) -> RenderCommandResult {
116 let Some(Initialized(pipeline)) = world.resources.get::<Eventually<LinePipeline>>() else {
117 return RenderCommandResult::Failure;
118 };
119
120 pass.set_render_pipeline(pipeline);
121 RenderCommandResult::Success
122 }
123}
124
125pub type DrawVectorTiles = (SetVectorTilePipeline, DrawVectorTile);
126pub type DrawLineTiles = (SetLineTilePipeline, DrawVectorTile);