mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Rename some functions and revert some changes
This commit is contained in:
parent
d8c2844d3d
commit
7a42abf06d
@ -1,10 +1,9 @@
|
||||
|
||||
use crate::coords::WorldCoords;
|
||||
use crate::io::tile_cache::TileCache;
|
||||
|
||||
use crate::render::render_state::RenderState;
|
||||
|
||||
use cgmath::{Vector2};
|
||||
use cgmath::Vector2;
|
||||
use log::info;
|
||||
use std::time::Duration;
|
||||
use winit::event::{ElementState, MouseButton};
|
||||
|
||||
@ -98,7 +98,7 @@ pub async fn run(
|
||||
scheduler.try_populate_cache();
|
||||
|
||||
input.update_state(state, scheduler.get_tile_cache(), dt);
|
||||
state.upload_tile_geometry(&mut scheduler);
|
||||
state.prepare_render_data(&mut scheduler);
|
||||
match state.render() {
|
||||
Ok(_) => {}
|
||||
Err(wgpu::SurfaceError::Lost) => {
|
||||
|
||||
@ -133,36 +133,32 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, TM: bytemuck::Pod, FM:
|
||||
(bytes, aligned_bytes)
|
||||
}
|
||||
|
||||
/// FIXME: use an id instead of layer_name to identify tiles
|
||||
pub fn get_loaded_layers_at(&self, coords: &WorldTileCoords) -> HashSet<&str> {
|
||||
if let Some(layers) = self.index.get_layers(coords) {
|
||||
pub fn get_loaded_layers_at(&self, coords: &WorldTileCoords) -> Option<HashSet<&str>> {
|
||||
self.index.get_layers(coords).map(|layers| {
|
||||
layers
|
||||
.iter()
|
||||
.map(|entry| entry.style_layer.source_layer.as_ref().unwrap().as_str())
|
||||
.collect()
|
||||
} else {
|
||||
HashSet::new()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Allocates
|
||||
/// * `geometry`
|
||||
/// * `tile_metadata` and
|
||||
/// * `feature_metadata` for a tile. This function is able to dynamically evict tiles if there
|
||||
/// * `layer_metadata` and
|
||||
/// * `feature_metadata` for a layer. This function is able to dynamically evict layers if there
|
||||
/// is not enough space available.
|
||||
pub fn allocate_tile_geometry(
|
||||
pub fn allocate_layer_geometry(
|
||||
&mut self,
|
||||
queue: &Q,
|
||||
coords: WorldTileCoords,
|
||||
style_layer: StyleLayer,
|
||||
geometry: &OverAlignedVertexBuffer<V, I>,
|
||||
tile_metadata: TM,
|
||||
layer_metadata: TM,
|
||||
feature_metadata: &[FM],
|
||||
empty: bool,
|
||||
) {
|
||||
let vertices_stride = size_of::<V>() as wgpu::BufferAddress;
|
||||
let indices_stride = size_of::<I>() as wgpu::BufferAddress;
|
||||
let tile_metadata_stride = size_of::<TM>() as wgpu::BufferAddress;
|
||||
let layer_metadata_stride = size_of::<TM>() as wgpu::BufferAddress;
|
||||
let feature_metadata_stride = size_of::<FM>() as wgpu::BufferAddress;
|
||||
|
||||
let (vertices_bytes, aligned_vertices_bytes) = Self::align(
|
||||
@ -175,8 +171,8 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, TM: bytemuck::Pod, FM:
|
||||
geometry.buffer.indices.len() as BufferAddress,
|
||||
geometry.usable_indices as BufferAddress,
|
||||
);
|
||||
let (tile_metadata_bytes, aligned_tile_metadata_bytes) =
|
||||
Self::align(tile_metadata_stride, 1, 1);
|
||||
let (layer_metadata_bytes, aligned_layer_metadata_bytes) =
|
||||
Self::align(layer_metadata_stride, 1, 1);
|
||||
|
||||
let (feature_metadata_bytes, aligned_feature_metadata_bytes) = Self::align(
|
||||
feature_metadata_stride,
|
||||
@ -197,63 +193,57 @@ impl<Q: Queue<B>, B, V: bytemuck::Pod, I: bytemuck::Pod, TM: bytemuck::Pod, FM:
|
||||
buffer_vertices: self.vertices.make_room(vertices_bytes, &mut self.index),
|
||||
buffer_indices: self.indices.make_room(indices_bytes, &mut self.index),
|
||||
usable_indices: geometry.usable_indices as u32,
|
||||
buffer_tile_metadata: self
|
||||
buffer_layer_metadata: self
|
||||
.metadata
|
||||
.make_room(tile_metadata_bytes, &mut self.index),
|
||||
.make_room(layer_metadata_bytes, &mut self.index),
|
||||
buffer_feature_metadata: self
|
||||
.feature_metadata
|
||||
.make_room(feature_metadata_bytes, &mut self.index),
|
||||
empty,
|
||||
};
|
||||
|
||||
// write_buffer() is the preferred method for WASM: https://toji.github.io/webgpu-best-practices/buffer-uploads.html#when-in-doubt-writebuffer
|
||||
if !maybe_entry.buffer_vertices.is_empty() {
|
||||
queue.write_buffer(
|
||||
&self.vertices.inner,
|
||||
maybe_entry.buffer_vertices.start,
|
||||
&bytemuck::cast_slice(&geometry.buffer.vertices)
|
||||
[0..aligned_vertices_bytes as usize],
|
||||
);
|
||||
}
|
||||
if !maybe_entry.buffer_indices.is_empty() {
|
||||
queue.write_buffer(
|
||||
&self.indices.inner,
|
||||
maybe_entry.buffer_indices.start,
|
||||
&bytemuck::cast_slice(&geometry.buffer.indices)[0..aligned_indices_bytes as usize],
|
||||
);
|
||||
}
|
||||
if !maybe_entry.buffer_tile_metadata.is_empty() {
|
||||
queue.write_buffer(
|
||||
&self.metadata.inner,
|
||||
maybe_entry.buffer_tile_metadata.start,
|
||||
&bytemuck::cast_slice(&[tile_metadata])[0..aligned_tile_metadata_bytes as usize],
|
||||
);
|
||||
}
|
||||
if !maybe_entry.buffer_feature_metadata.is_empty() {
|
||||
queue.write_buffer(
|
||||
&self.feature_metadata.inner,
|
||||
maybe_entry.buffer_feature_metadata.start,
|
||||
&bytemuck::cast_slice(feature_metadata)[0..aligned_feature_metadata_bytes as usize],
|
||||
);
|
||||
}
|
||||
queue.write_buffer(
|
||||
&self.vertices.inner,
|
||||
maybe_entry.buffer_vertices.start,
|
||||
&bytemuck::cast_slice(&geometry.buffer.vertices)[0..aligned_vertices_bytes as usize],
|
||||
);
|
||||
|
||||
queue.write_buffer(
|
||||
&self.indices.inner,
|
||||
maybe_entry.buffer_indices.start,
|
||||
&bytemuck::cast_slice(&geometry.buffer.indices)[0..aligned_indices_bytes as usize],
|
||||
);
|
||||
|
||||
queue.write_buffer(
|
||||
&self.metadata.inner,
|
||||
maybe_entry.buffer_layer_metadata.start,
|
||||
&bytemuck::cast_slice(&[layer_metadata])[0..aligned_layer_metadata_bytes as usize],
|
||||
);
|
||||
|
||||
queue.write_buffer(
|
||||
&self.feature_metadata.inner,
|
||||
maybe_entry.buffer_feature_metadata.start,
|
||||
&bytemuck::cast_slice(feature_metadata)[0..aligned_feature_metadata_bytes as usize],
|
||||
);
|
||||
|
||||
self.index.push_back(maybe_entry);
|
||||
}
|
||||
|
||||
pub fn update_tile_metadata(&self, queue: &Q, entry: &IndexEntry, tile_metadata: TM) {
|
||||
let tile_metadata_stride = size_of::<TM>() as wgpu::BufferAddress; // TODO: deduplicate
|
||||
let (tile_metadata_bytes, aligned_tile_metadata_bytes) =
|
||||
Self::align(tile_metadata_stride, 1, 1);
|
||||
pub fn update_layer_metadata(&self, queue: &Q, entry: &IndexEntry, layer_metadata: TM) {
|
||||
let layer_metadata_stride = size_of::<TM>() as wgpu::BufferAddress; // TODO: deduplicate
|
||||
let (layer_metadata_bytes, aligned_layer_metadata_bytes) =
|
||||
Self::align(layer_metadata_stride, 1, 1);
|
||||
|
||||
if entry.buffer_tile_metadata.end - entry.buffer_tile_metadata.start != tile_metadata_bytes
|
||||
if entry.buffer_layer_metadata.end - entry.buffer_layer_metadata.start
|
||||
!= layer_metadata_bytes
|
||||
{
|
||||
panic!("Updated tile metadata has wrong size!");
|
||||
panic!("Updated layer metadata has wrong size!");
|
||||
}
|
||||
|
||||
queue.write_buffer(
|
||||
&self.metadata.inner,
|
||||
entry.buffer_tile_metadata.start,
|
||||
&bytemuck::cast_slice(&[tile_metadata])[0..aligned_tile_metadata_bytes as usize],
|
||||
entry.buffer_layer_metadata.start,
|
||||
&bytemuck::cast_slice(&[layer_metadata])[0..aligned_layer_metadata_bytes as usize],
|
||||
);
|
||||
}
|
||||
|
||||
@ -320,13 +310,13 @@ impl<B> BackingBuffer<B> {
|
||||
let start = index.front().map(|first| match self.typ {
|
||||
BackingBufferType::Vertices => first.buffer_vertices.start,
|
||||
BackingBufferType::Indices => first.buffer_indices.start,
|
||||
BackingBufferType::Metadata => first.buffer_tile_metadata.start,
|
||||
BackingBufferType::Metadata => first.buffer_layer_metadata.start,
|
||||
BackingBufferType::FeatureMetadata => first.buffer_feature_metadata.start,
|
||||
});
|
||||
let end = index.back().map(|first| match self.typ {
|
||||
BackingBufferType::Vertices => first.buffer_vertices.end,
|
||||
BackingBufferType::Indices => first.buffer_indices.end,
|
||||
BackingBufferType::Metadata => first.buffer_tile_metadata.end,
|
||||
BackingBufferType::Metadata => first.buffer_layer_metadata.end,
|
||||
BackingBufferType::FeatureMetadata => first.buffer_feature_metadata.end,
|
||||
});
|
||||
|
||||
@ -367,13 +357,12 @@ pub struct IndexEntry {
|
||||
// Range of bytes within the backing buffer for indices
|
||||
buffer_indices: Range<wgpu::BufferAddress>,
|
||||
// Range of bytes within the backing buffer for metadata
|
||||
buffer_tile_metadata: Range<wgpu::BufferAddress>,
|
||||
buffer_layer_metadata: Range<wgpu::BufferAddress>,
|
||||
// Range of bytes within the backing buffer for feature metadata
|
||||
buffer_feature_metadata: Range<wgpu::BufferAddress>,
|
||||
// Amount of actually usable indices. Each index has the size/format `IndexDataType`.
|
||||
// Can be lower than size(buffer_indices) / indices_stride because of alignment.
|
||||
usable_indices: u32,
|
||||
pub empty: bool,
|
||||
}
|
||||
|
||||
impl IndexEntry {
|
||||
@ -389,8 +378,8 @@ impl IndexEntry {
|
||||
self.buffer_vertices.clone()
|
||||
}
|
||||
|
||||
pub fn tile_metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
|
||||
self.buffer_tile_metadata.clone()
|
||||
pub fn layer_metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
|
||||
self.buffer_layer_metadata.clone()
|
||||
}
|
||||
|
||||
pub fn feature_metadata_buffer_range(&self) -> Range<wgpu::BufferAddress> {
|
||||
@ -430,46 +419,26 @@ impl RingIndex {
|
||||
.and_then(|key| self.tree_index.get(&key))
|
||||
}
|
||||
|
||||
pub fn get_layers_fallback(
|
||||
&self,
|
||||
coords: &WorldTileCoords,
|
||||
) -> Option<(&VecDeque<IndexEntry>, &IndexEntry)> {
|
||||
pub fn get_layers_fallback(&self, coords: &WorldTileCoords) -> Option<&VecDeque<IndexEntry>> {
|
||||
let mut current = *coords;
|
||||
let mut first_mask_entry: Option<&IndexEntry> = None;
|
||||
loop {
|
||||
if let Some((entries, mask_entry)) = self
|
||||
.get_layers(¤t)
|
||||
.map(|entries| (entries, entries.front()))
|
||||
{
|
||||
if let Some(mask_entry) = mask_entry {
|
||||
if let None = first_mask_entry {
|
||||
first_mask_entry = Some(&mask_entry);
|
||||
}
|
||||
|
||||
if mask_entry.empty {
|
||||
if let Some(parent) = current.get_parent() {
|
||||
// Continue with parent because there is no data in current tile
|
||||
current = parent
|
||||
} else {
|
||||
// We do not have a parent tile with actual data, do not render
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
// Return actual data
|
||||
return Some((entries, first_mask_entry.unwrap()));
|
||||
}
|
||||
} else {
|
||||
// No data to we can not draw this tile yet
|
||||
return None;
|
||||
}
|
||||
if let Some(entries) = self.get_layers(¤t) {
|
||||
return Some(entries);
|
||||
} else if let Some(parent) = current.get_parent() {
|
||||
current = parent
|
||||
} else {
|
||||
// No data to we can not draw this tile yet
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop_front(&mut self) -> Option<IndexEntry> {
|
||||
pub fn iter(&self) -> impl Iterator<Item = &VecDeque<IndexEntry>> + '_ {
|
||||
self.linear_index
|
||||
.iter()
|
||||
.flat_map(|key| self.tree_index.get(key))
|
||||
}
|
||||
|
||||
fn pop_front(&mut self) -> Option<IndexEntry> {
|
||||
if let Some(entries) = self
|
||||
.linear_index
|
||||
.pop_front()
|
||||
@ -481,7 +450,7 @@ impl RingIndex {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_back(&mut self, entry: IndexEntry) {
|
||||
fn push_back(&mut self, entry: IndexEntry) {
|
||||
if let Some(key) = entry.coords.build_quad_key() {
|
||||
match self.tree_index.entry(key) {
|
||||
btree_map::Entry::Vacant(index_entry) => {
|
||||
@ -493,15 +462,9 @@ impl RingIndex {
|
||||
}
|
||||
|
||||
self.linear_index.push_back(key)
|
||||
} else {
|
||||
unreachable!() // TODO handle
|
||||
}
|
||||
|
||||
// TODO Else
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &VecDeque<IndexEntry>> + '_ {
|
||||
self.linear_index
|
||||
.iter()
|
||||
.flat_map(|key| self.tree_index.get(key))
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,7 +530,7 @@ mod tests {
|
||||
let data24bytes_aligned = data24bytes.into();
|
||||
|
||||
for _ in 0..2 {
|
||||
pool.allocate_tile_geometry(
|
||||
pool.allocate_layer_geometry(
|
||||
&queue,
|
||||
(0, 0, 0).into(),
|
||||
style_layer.clone(),
|
||||
@ -581,7 +544,7 @@ mod tests {
|
||||
pool.available_space(BackingBufferType::Vertices)
|
||||
);
|
||||
|
||||
pool.allocate_tile_geometry(
|
||||
pool.allocate_layer_geometry(
|
||||
&queue,
|
||||
(0, 0, 0).into(),
|
||||
style_layer.clone(),
|
||||
@ -595,7 +558,7 @@ mod tests {
|
||||
);
|
||||
println!("{:?}", &pool.index);
|
||||
|
||||
pool.allocate_tile_geometry(
|
||||
pool.allocate_layer_geometry(
|
||||
&queue,
|
||||
(0, 0, 0).into(),
|
||||
style_layer.clone(),
|
||||
@ -607,7 +570,7 @@ mod tests {
|
||||
println!("{:?}", &pool.index);
|
||||
assert_eq!(24, pool.available_space(BackingBufferType::Vertices));
|
||||
|
||||
pool.allocate_tile_geometry(
|
||||
pool.allocate_layer_geometry(
|
||||
&queue,
|
||||
(0, 0, 0).into(),
|
||||
style_layer.clone(),
|
||||
@ -618,7 +581,7 @@ mod tests {
|
||||
println!("{:?}", &pool.index);
|
||||
assert_eq!(0, pool.available_space(BackingBufferType::Vertices));
|
||||
|
||||
pool.allocate_tile_geometry(
|
||||
pool.allocate_layer_geometry(
|
||||
&queue,
|
||||
(0, 0, 0).into(),
|
||||
style_layer.clone(),
|
||||
@ -629,7 +592,7 @@ mod tests {
|
||||
println!("{:?}", &pool.index);
|
||||
assert_eq!(24, pool.available_space(BackingBufferType::Vertices));
|
||||
|
||||
pool.allocate_tile_geometry(
|
||||
pool.allocate_layer_geometry(
|
||||
&queue,
|
||||
(0, 0, 0).into(),
|
||||
style_layer,
|
||||
|
||||
@ -16,6 +16,7 @@ use winit::window::Window;
|
||||
use crate::platform::{COLOR_TEXTURE_FORMAT, MIN_BUFFER_SIZE};
|
||||
use crate::render::buffer_pool::{BackingBufferDescriptor, BufferPool, IndexEntry};
|
||||
use crate::render::camera;
|
||||
use crate::render::camera::ViewProjection;
|
||||
use crate::render::options::{
|
||||
DEBUG_WIREFRAME, FEATURE_METADATA_BUFFER_SIZE, INDEX_FORMAT, INDICES_BUFFER_SIZE,
|
||||
TILE_META_COUNT, VERTEX_BUFFER_SIZE,
|
||||
@ -60,7 +61,7 @@ pub struct RenderState {
|
||||
Buffer,
|
||||
ShaderVertex,
|
||||
IndexDataType,
|
||||
ShaderTileMetadata,
|
||||
ShaderLayerMetadata,
|
||||
ShaderFeatureStyle,
|
||||
>,
|
||||
|
||||
@ -160,7 +161,7 @@ impl RenderState {
|
||||
cmp::max(MIN_BUFFER_SIZE, std::mem::size_of::<ShaderGlobals>() as u64);
|
||||
|
||||
let metadata_buffer_size =
|
||||
std::mem::size_of::<ShaderTileMetadata>() as u64 * TILE_META_COUNT;
|
||||
std::mem::size_of::<ShaderLayerMetadata>() as u64 * TILE_META_COUNT;
|
||||
let metadata_buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("Tiles ubo"),
|
||||
size: metadata_buffer_size,
|
||||
@ -350,38 +351,27 @@ impl RenderState {
|
||||
self.zoom.floor() as u8
|
||||
}
|
||||
|
||||
// TODO: Could we draw inspiration from StagingBelt (https://docs.rs/wgpu/latest/wgpu/util/struct.StagingBelt.html)?
|
||||
// TODO: What is StagingBelt for?
|
||||
pub fn upload_tile_geometry(&mut self, scheduler: &mut IOScheduler) {
|
||||
let visible_z = self.visible_z();
|
||||
/// Fetch tiles which are currently in view
|
||||
fn fetch_tiles_in_view(&self, view_region: &ViewRegion, scheduler: &mut IOScheduler) {
|
||||
let source_layers: HashSet<String> = self
|
||||
.style
|
||||
.layers
|
||||
.iter()
|
||||
.filter_map(|layer| layer.source_layer.clone())
|
||||
.collect();
|
||||
|
||||
let inverted_view_proj = self.camera.calc_view_proj(&self.perspective).invert();
|
||||
let view_region = self
|
||||
.camera
|
||||
.view_region_bounding_box(&inverted_view_proj)
|
||||
.map(|bounding_box| ViewRegion::new(bounding_box, 2, self.zoom, visible_z));
|
||||
|
||||
// Fetch tiles which are currently in view
|
||||
if let Some(view_region) = &view_region {
|
||||
let source_layers: HashSet<String> = self
|
||||
.style
|
||||
.layers
|
||||
.iter()
|
||||
.filter_map(|layer| layer.source_layer.clone())
|
||||
.collect();
|
||||
|
||||
for coords in view_region.iter() {
|
||||
if let Some(_) = coords.build_quad_key() {
|
||||
scheduler.try_request_tile(&coords, &source_layers).unwrap();
|
||||
}
|
||||
for coords in view_region.iter() {
|
||||
if let Some(_) = coords.build_quad_key() {
|
||||
// TODO: Make tesselation depend on style?
|
||||
scheduler.try_request_tile(&coords, &source_layers).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let view_proj = self.camera.calc_view_proj(&self.perspective);
|
||||
|
||||
// Update tile metadata for all required tiles on the GPU according to current zoom, camera and perspective
|
||||
// We perform the update before uploading new tessellated tiles, such that each
|
||||
// tile metadata in the the `buffer_pool` gets updated exactly once and not twice.
|
||||
/// Update tile metadata for all required tiles on the GPU according to current zoom, camera and perspective
|
||||
/// We perform the update before uploading new tessellated tiles, such that each
|
||||
/// tile metadata in the the `buffer_pool` gets updated exactly once and not twice.
|
||||
fn update_metadata(&self, view_proj: &ViewProjection) {
|
||||
for entries in self.buffer_pool.index().iter() {
|
||||
for entry in entries {
|
||||
let world_coords = entry.coords;
|
||||
@ -394,10 +384,12 @@ impl RenderState {
|
||||
.to_model_view_projection(world_coords.transform_for_zoom(self.zoom)))
|
||||
.downcast();
|
||||
|
||||
self.buffer_pool.update_tile_metadata(
|
||||
// TODO: Update features
|
||||
|
||||
self.buffer_pool.update_layer_metadata(
|
||||
&self.queue,
|
||||
entry,
|
||||
ShaderTileMetadata::new(
|
||||
ShaderLayerMetadata::new(
|
||||
transform.into(),
|
||||
zoom_factor,
|
||||
entry.style_layer.index as f32,
|
||||
@ -405,110 +397,115 @@ impl RenderState {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upload_tile_geometry(
|
||||
&mut self,
|
||||
view_proj: &ViewProjection,
|
||||
view_region: &ViewRegion,
|
||||
scheduler: &mut IOScheduler,
|
||||
) {
|
||||
let visible_z = self.visible_z();
|
||||
|
||||
// Factor which determines how much we need to adjust the width of lines for example.
|
||||
// If zoom == z -> zoom_factor == 1
|
||||
let zoom_factor = 2.0_f64.powf(visible_z as f64 - self.zoom) as f32; // TODO deduplicate
|
||||
|
||||
// Upload all tessellated layers which are in view
|
||||
if let Some(view_region) = &view_region {
|
||||
for world_coords in view_region.iter() {
|
||||
let loaded_layers = self.buffer_pool.get_loaded_layers_at(&world_coords);
|
||||
for world_coords in view_region.iter() {
|
||||
let loaded_layers = self
|
||||
.buffer_pool
|
||||
.get_loaded_layers_at(&world_coords)
|
||||
.unwrap_or_default();
|
||||
if let Some(available_layers) = scheduler
|
||||
.get_tile_cache()
|
||||
.iter_tessellated_layers_at(&world_coords, &loaded_layers)
|
||||
.map(|layers| layers.collect::<Vec<_>>())
|
||||
{
|
||||
for style_layer in &self.style.layers {
|
||||
let source_layer = style_layer.source_layer.as_ref().unwrap();
|
||||
|
||||
if let Some(available_layers) = scheduler
|
||||
.get_tile_cache()
|
||||
.iter_tessellated_layers_at(&world_coords, &loaded_layers)
|
||||
.map(|layers| layers.collect::<Vec<_>>())
|
||||
{
|
||||
for style_layer in &self.style.layers {
|
||||
let source_layer = style_layer.source_layer.as_ref().unwrap();
|
||||
if let Some(result) = available_layers
|
||||
.iter()
|
||||
.find(|layer| source_layer.as_str() == layer.layer_name())
|
||||
{
|
||||
let color: Option<Vec4f32> = style_layer
|
||||
.paint
|
||||
.as_ref()
|
||||
.and_then(|paint| paint.get_color())
|
||||
.map(|color| color.into());
|
||||
|
||||
if let Some(result) = available_layers
|
||||
.iter()
|
||||
.find(|layer| source_layer.as_str() == layer.layer_name())
|
||||
{
|
||||
let color: Option<Vec4f32> = style_layer
|
||||
.paint
|
||||
.as_ref()
|
||||
.and_then(|paint| paint.get_color())
|
||||
.map(|color| color.into());
|
||||
match result {
|
||||
LayerTessellateResult::UnavailableLayer { coords, .. } => {
|
||||
/*self.buffer_pool.mark_layer_unavailable(*coords);*/
|
||||
}
|
||||
LayerTessellateResult::TessellatedLayer {
|
||||
coords,
|
||||
feature_indices,
|
||||
layer_data,
|
||||
buffer,
|
||||
..
|
||||
} => {
|
||||
let world_coords = coords;
|
||||
|
||||
match result {
|
||||
LayerTessellateResult::UnavailableLayer { coords, .. } => {
|
||||
// We are casting here from 64bit to 32bit, because 32bit is more performant and is
|
||||
// better supported.
|
||||
let transform: Matrix4<f32> = (view_proj
|
||||
.to_model_view_projection(
|
||||
world_coords.transform_for_zoom(self.zoom),
|
||||
))
|
||||
.downcast();
|
||||
|
||||
let tile_metadata = ShaderTileMetadata::new(
|
||||
transform.into(),
|
||||
zoom_factor,
|
||||
style_layer.index as f32,
|
||||
);
|
||||
println!("unavailable layer");
|
||||
self.buffer_pool.allocate_tile_geometry(
|
||||
&self.queue,
|
||||
*coords,
|
||||
style_layer.clone(),
|
||||
&OverAlignedVertexBuffer::empty(),
|
||||
tile_metadata,
|
||||
&[],
|
||||
true,
|
||||
);
|
||||
}
|
||||
LayerTessellateResult::TessellatedLayer {
|
||||
coords,
|
||||
feature_indices,
|
||||
layer_data,
|
||||
buffer,
|
||||
..
|
||||
} => {
|
||||
let world_coords = coords;
|
||||
|
||||
let feature_metadata = layer_data
|
||||
.features()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, _feature)| {
|
||||
iter::repeat(ShaderFeatureStyle {
|
||||
color: color.unwrap(),
|
||||
})
|
||||
.take(feature_indices[i] as usize)
|
||||
let feature_metadata = layer_data
|
||||
.features()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, _feature)| {
|
||||
iter::repeat(ShaderFeatureStyle {
|
||||
color: color.unwrap(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
.take(feature_indices[i] as usize)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// We are casting here from 64bit to 32bit, because 32bit is more performant and is
|
||||
// better supported.
|
||||
let transform: Matrix4<f32> = (view_proj
|
||||
.to_model_view_projection(
|
||||
world_coords.transform_for_zoom(self.zoom),
|
||||
))
|
||||
.downcast();
|
||||
// We are casting here from 64bit to 32bit, because 32bit is more performant and is
|
||||
// better supported.
|
||||
let transform: Matrix4<f32> = (view_proj.to_model_view_projection(
|
||||
world_coords.transform_for_zoom(self.zoom),
|
||||
))
|
||||
.downcast();
|
||||
|
||||
let tile_metadata = ShaderTileMetadata::new(
|
||||
self.buffer_pool.allocate_layer_geometry(
|
||||
&self.queue,
|
||||
*coords,
|
||||
style_layer.clone(),
|
||||
buffer,
|
||||
ShaderLayerMetadata::new(
|
||||
transform.into(),
|
||||
zoom_factor,
|
||||
style_layer.index as f32,
|
||||
);
|
||||
self.buffer_pool.allocate_tile_geometry(
|
||||
&self.queue,
|
||||
*coords,
|
||||
style_layer.clone(),
|
||||
buffer,
|
||||
tile_metadata,
|
||||
&feature_metadata,
|
||||
false,
|
||||
);
|
||||
}
|
||||
),
|
||||
&feature_metadata,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prepare_render_data(&mut self, scheduler: &mut IOScheduler) {
|
||||
let visible_z = self.visible_z();
|
||||
|
||||
let view_region = self
|
||||
.camera
|
||||
.view_region_bounding_box(&self.camera.calc_view_proj(&self.perspective).invert())
|
||||
.map(|bounding_box| ViewRegion::new(bounding_box, 2, self.zoom, visible_z));
|
||||
|
||||
let view_proj = self.camera.calc_view_proj(&self.perspective);
|
||||
|
||||
self.update_metadata(&view_proj);
|
||||
|
||||
if let Some(view_region) = &view_region {
|
||||
self.upload_tile_geometry(&view_proj, &view_region, scheduler);
|
||||
self.fetch_tiles_in_view(view_region, scheduler);
|
||||
}
|
||||
|
||||
// TODO: Could we draw inspiration from StagingBelt (https://docs.rs/wgpu/latest/wgpu/util/struct.StagingBelt.html)?
|
||||
// TODO: What is StagingBelt for?
|
||||
|
||||
// Update globals
|
||||
self.queue.write_buffer(
|
||||
@ -587,9 +584,7 @@ impl RenderState {
|
||||
for world_coords in view_region.iter() {
|
||||
/* println!("Render coordinate {:?}", world_coords);*/
|
||||
|
||||
if let Some((entries, mask_entry)) =
|
||||
index.get_layers_fallback(&world_coords)
|
||||
{
|
||||
if let Some(entries) = index.get_layers_fallback(&world_coords) {
|
||||
let mut to_render: Vec<&IndexEntry> = Vec::from_iter(entries);
|
||||
to_render.sort_by_key(|entry| entry.style_layer.index);
|
||||
|
||||
@ -601,23 +596,21 @@ impl RenderState {
|
||||
/* println!("Render mask");*/
|
||||
|
||||
// Draw mask
|
||||
{
|
||||
pass.set_pipeline(&self.mask_pipeline);
|
||||
pass.set_stencil_reference(reference);
|
||||
pass.set_vertex_buffer(
|
||||
0,
|
||||
self.buffer_pool
|
||||
.metadata()
|
||||
.slice(mask_entry.tile_metadata_buffer_range()),
|
||||
);
|
||||
pass.draw(0..6, 0..1);
|
||||
if let Some(mask_entry) = entries.front() {
|
||||
{
|
||||
pass.set_pipeline(&self.mask_pipeline);
|
||||
pass.set_stencil_reference(reference);
|
||||
pass.set_vertex_buffer(
|
||||
0,
|
||||
self.buffer_pool
|
||||
.metadata()
|
||||
.slice(mask_entry.layer_metadata_buffer_range()),
|
||||
);
|
||||
pass.draw(0..6, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
for entry in to_render {
|
||||
if entry.empty {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Draw tile
|
||||
{
|
||||
/* println!("Render tile");*/
|
||||
@ -640,7 +633,7 @@ impl RenderState {
|
||||
1,
|
||||
self.buffer_pool
|
||||
.metadata()
|
||||
.slice(entry.tile_metadata_buffer_range()),
|
||||
.slice(entry.layer_metadata_buffer_range()),
|
||||
);
|
||||
pass.set_vertex_buffer(
|
||||
2,
|
||||
|
||||
@ -80,7 +80,7 @@ impl VertexShaderState {
|
||||
}
|
||||
|
||||
pub mod tile {
|
||||
use super::{ShaderTileMetadata, ShaderVertex};
|
||||
use super::{ShaderLayerMetadata, ShaderVertex};
|
||||
use crate::platform::COLOR_TEXTURE_FORMAT;
|
||||
use crate::render::shaders::ShaderFeatureStyle;
|
||||
|
||||
@ -110,7 +110,7 @@ pub mod tile {
|
||||
},
|
||||
// tile metadata
|
||||
wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<ShaderTileMetadata>() as u64,
|
||||
array_stride: std::mem::size_of::<ShaderLayerMetadata>() as u64,
|
||||
step_mode: wgpu::VertexStepMode::Instance,
|
||||
attributes: &[
|
||||
// translate
|
||||
@ -188,7 +188,7 @@ pub mod tile {
|
||||
pub mod tile_mask {
|
||||
use crate::platform::COLOR_TEXTURE_FORMAT;
|
||||
use crate::render::options::DEBUG_STENCIL_PATTERN;
|
||||
use crate::render::shaders::ShaderTileMetadata;
|
||||
use crate::render::shaders::ShaderLayerMetadata;
|
||||
use wgpu::ColorWrites;
|
||||
|
||||
use super::{FragmentShaderState, VertexShaderState};
|
||||
@ -196,7 +196,7 @@ pub mod tile_mask {
|
||||
pub const VERTEX: VertexShaderState = VertexShaderState::new(
|
||||
include_str!("tile_mask.vertex.wgsl"),
|
||||
&[wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<ShaderTileMetadata>() as u64,
|
||||
array_stride: std::mem::size_of::<ShaderLayerMetadata>() as u64,
|
||||
step_mode: wgpu::VertexStepMode::Instance,
|
||||
attributes: &[
|
||||
// translate
|
||||
@ -308,13 +308,13 @@ pub struct ShaderFeatureStyle {
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||
pub struct ShaderTileMetadata {
|
||||
pub struct ShaderLayerMetadata {
|
||||
pub transform: Mat4x4f32,
|
||||
pub zoom_factor: f32,
|
||||
pub z_index: f32,
|
||||
}
|
||||
|
||||
impl ShaderTileMetadata {
|
||||
impl ShaderLayerMetadata {
|
||||
pub fn new(transform: Mat4x4f32, zoom_factor: f32, z_index: f32) -> Self {
|
||||
Self {
|
||||
transform,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user