# upload_system.rs - source
Source of the Rust file `maplibre/src/raster/upload_system.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
    110
    111

    //! Uploads data to the GPU which is needed for rendering.
    use crate::{
        context::MapContext,
        coords::ViewRegion,
        raster::{
            resource::RasterResources, AvailableRasterLayerData, RasterLayerData,
            RasterLayersDataComponent,
        },
        render::{
            eventually::{Eventually, Eventually::Initialized},
            tile_view_pattern::DEFAULT_TILE_SIZE,
            Renderer,
        },
        style::Style,
        tcs::tiles::Tiles,
    };

    pub fn upload_system(
        MapContext {
            world,
            style,
            view_state,
            renderer: Renderer { device, queue, .. },
            ..
        }: &mut MapContext,
    ) {
        let Some(Initialized(raster_resources)) = world
            .resources
            .query_mut::<&mut Eventually<RasterResources>>()
        else {
            return;
        };
        let view_region =
            view_state.create_view_region(view_state.zoom().zoom_level(DEFAULT_TILE_SIZE));

        if let Some(view_region) = &view_region {
            upload_raster_layer(
                raster_resources,
                device,
                queue,
                &world.tiles,
                style,
                view_region,
            );
        }
    }

    #[tracing::instrument(skip_all)]
    fn upload_raster_layer(
        raster_resources: &mut RasterResources,
        device: &wgpu::Device,
        queue: &wgpu::Queue,
        tiles: &Tiles,
        style: &Style,
        view_region: &ViewRegion,
    ) {
        for coords in view_region.iter() {
            if raster_resources.get_bound_texture(&coords).is_some() {
                continue;
            }

            let Some(raster_layers) = tiles.query::<&RasterLayersDataComponent>(coords) else {
                continue;
            };

            for style_layer in &style.layers {
                let style_source_layer = style_layer.source_layer.as_ref().unwrap(); // FIXME: Remove unwrap

                let Some(AvailableRasterLayerData { coords, image, .. }) = raster_layers
                    .layers
                    .iter()
                    .flat_map(|data| match data {
                        RasterLayerData::Available(data) => Some(data),
                        RasterLayerData::Missing(_) => None,
                    })
                    .find(|layer| style_source_layer.as_str() == layer.source_layer)
                else {
                    continue;
                };

                let (width, height) = image.dimensions();

                let texture = raster_resources.create_texture(
                    None,
                    device,
                    wgpu::TextureFormat::Rgba8UnormSrgb,
                    width,
                    height,
                    wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
                );

                queue.write_texture(
                    wgpu::ImageCopyTexture {
                        aspect: wgpu::TextureAspect::All,
                        texture: &texture.texture,
                        mip_level: 0,
                        origin: wgpu::Origin3d::ZERO,
                    },
                    image,
                    wgpu::ImageDataLayout {
                        offset: 0,
                        bytes_per_row: Some(4 * width),
                        rows_per_image: Some(height),
                    },
                    texture.size,
                );

                raster_resources.bind_texture(device, coords, texture);
            }
        }
    }