maplibre/raster/
upload_system.rs1use crate::{
3 context::MapContext,
4 coords::ViewRegion,
5 raster::{
6 resource::RasterResources, AvailableRasterLayerData, RasterLayerData,
7 RasterLayersDataComponent,
8 },
9 render::{
10 eventually::{Eventually, Eventually::Initialized},
11 tile_view_pattern::DEFAULT_TILE_SIZE,
12 view_state::ViewStatePadding,
13 Renderer,
14 },
15 style::Style,
16 tcs::{
17 system::{SystemError, SystemResult},
18 tiles::Tiles,
19 },
20};
21
22pub fn upload_system(
23 MapContext {
24 world,
25 style,
26 view_state,
27 renderer: Renderer { device, queue, .. },
28 ..
29 }: &mut MapContext,
30) -> SystemResult {
31 let Some(Initialized(raster_resources)) = world
32 .resources
33 .query_mut::<&mut Eventually<RasterResources>>()
34 else {
35 return Err(SystemError::Dependencies);
36 };
37 let view_region = view_state.create_view_region(
38 view_state.zoom().zoom_level(DEFAULT_TILE_SIZE),
39 ViewStatePadding::Loose,
40 );
41
42 if let Some(view_region) = &view_region {
43 upload_raster_layer(
44 raster_resources,
45 device,
46 queue,
47 &world.tiles,
48 style,
49 view_region,
50 );
51 }
52
53 Ok(())
54}
55
56#[tracing::instrument(skip_all)]
57fn upload_raster_layer(
58 raster_resources: &mut RasterResources,
59 device: &wgpu::Device,
60 queue: &wgpu::Queue,
61 tiles: &Tiles,
62 style: &Style,
63 view_region: &ViewRegion,
64) {
65 for coords in view_region.iter() {
66 if raster_resources.get_bound_texture(&coords).is_some() {
67 continue;
68 }
69
70 let Some(raster_layers) = tiles.query::<&RasterLayersDataComponent>(coords) else {
71 continue;
72 };
73
74 for style_layer in &style.layers {
75 let style_source_layer = style_layer.source_layer.as_ref().unwrap(); let Some(AvailableRasterLayerData { coords, image, .. }) = raster_layers
78 .layers
79 .iter()
80 .flat_map(|data| match data {
81 RasterLayerData::Available(data) => Some(data),
82 RasterLayerData::Missing(_) => None,
83 })
84 .find(|layer| style_source_layer.as_str() == layer.source_layer)
85 else {
86 continue;
87 };
88
89 let (width, height) = image.dimensions();
90
91 let texture = raster_resources.create_texture(
92 None,
93 device,
94 wgpu::TextureFormat::Rgba8UnormSrgb,
95 width,
96 height,
97 wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
98 );
99
100 queue.write_texture(
101 wgpu::ImageCopyTexture {
102 aspect: wgpu::TextureAspect::All,
103 texture: &texture.texture,
104 mip_level: 0,
105 origin: wgpu::Origin3d::ZERO,
106 },
107 image,
108 wgpu::ImageDataLayout {
109 offset: 0,
110 bytes_per_row: Some(4 * width),
111 rows_per_image: Some(height),
112 },
113 texture.size,
114 );
115
116 raster_resources.bind_texture(device, coords, texture);
117 }
118 }
119}