Skip to content

Commit

Permalink
Revamp program structure for better memory performance. While this is…
Browse files Browse the repository at this point in the history
… ok now, loading new tiles makes the renderer stutter ...
  • Loading branch information
Yatekii committed Sep 5, 2019
1 parent 703464a commit 6c81997
Show file tree
Hide file tree
Showing 13 changed files with 302 additions and 241 deletions.
2 changes: 1 addition & 1 deletion config/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ui_font = "config/Ruda-Bold.ttf"
max_tiles = 200
max_features = 1000
tile_size = 384
msaa_samples = 4
msaa_samples = 1
selection_tags = []

[renderer.temperature]
Expand Down
94 changes: 94 additions & 0 deletions src/bin/app_state.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
use std::collections::BTreeMap;
use std::sync::{
Arc,
RwLock,
};
use lyon::math::Point;
use crate::*;
use stats::Stats;
Expand All @@ -11,6 +16,8 @@ pub struct AppState {
pub hovered_objects: Vec<Object>,
pub selected_objects: Vec<EditableObject>,
pub stats: Stats,
visible_tiles: BTreeMap<TileId, VisibleTile>,
feature_collection: Arc<RwLock<FeatureCollection>>,
}

impl AppState {
Expand All @@ -31,6 +38,93 @@ impl AppState {
hovered_objects: vec![],
selected_objects: vec![],
stats: Stats::new(),
visible_tiles: BTreeMap::new(),
feature_collection: Arc::new(RwLock::new(FeatureCollection::new(CONFIG.renderer.max_features as u32))),
}
}

pub fn visible_tiles(&self) -> &BTreeMap<TileId, VisibleTile> {
&self.visible_tiles
}

pub fn feature_collection(&self) -> Arc<RwLock<FeatureCollection>> {
self.feature_collection.clone()
}

pub fn load_tiles(&mut self) {
let tile_field = self.screen.get_tile_boundaries_for_zoom_level(self.zoom, 1);

// Remove old bigger tiles which are not in the FOV anymore.
let old_tile_field = self.screen.get_tile_boundaries_for_zoom_level(self.zoom - 1.0, 2);
let key_iter: Vec<_> = self.visible_tiles.keys().copied().collect();
for key in key_iter {
if key.z == (self.zoom - 1.0) as u32 {
if !old_tile_field.contains(&key) {
self.visible_tiles.remove(&key);
}
} else {
if !tile_field.contains(&key) {
self.visible_tiles.remove(&key);
}
}
}

self.tile_cache.finalize_loaded_tiles();
for tile_id in tile_field.iter() {
if !self.visible_tiles.contains_key(&tile_id) {
self.tile_cache.request_tile(&tile_id, self.feature_collection.clone(), &CONFIG.renderer.selection_tags.clone());

let tile_cache = &mut self.tile_cache;
if let Some(tile) = tile_cache.try_get_tile(&tile_id) {

let mut visible_tile = VisibleTile::new(tile);

visible_tile.load_collider();

self.visible_tiles.insert(
tile_id.clone(),
visible_tile
);

// Remove old bigger tile when all 4 smaller tiles are loaded.
let mut count = 0;
let num_x = (tile_id.x / 2) * 2;
let num_y = (tile_id.y / 2) * 2;
for tile_id in &[
TileId::new(tile_id.z, num_x, num_y),
TileId::new(tile_id.z, num_x + 1, num_y),
TileId::new(tile_id.z, num_x + 1, num_y + 1),
TileId::new(tile_id.z, num_x, num_y + 1),
] {
if !tile_field.contains(tile_id) {
count += 1;
continue;
}
if self.visible_tiles.contains_key(tile_id) {
count += 1;
}
}
if count == 4 {
self.visible_tiles.remove(&TileId::new(tile_id.z - 1, num_x / 2, num_y / 2));
}

// Remove old smaller tiles when all 4 smaller tiles are loaded.
for tile_id in &[
TileId::new(tile_id.z + 1, tile_id.x * 2, tile_id.y * 2),
TileId::new(tile_id.z + 1, tile_id.x * 2 + 1, tile_id.y * 2),
TileId::new(tile_id.z + 1, tile_id.x * 2 + 1, tile_id.y * 2 + 1),
TileId::new(tile_id.z + 1, tile_id.x * 2, tile_id.y * 2 + 1),
] {
self.visible_tiles.remove(tile_id);
}
} else {
log::trace!("Could not read tile {} from cache.", tile_id);
}
}
}

if let Ok(mut feature_collection) = self.feature_collection.try_write() {
feature_collection.load_styles(self.zoom, &mut self.css_cache);
}
}

Expand Down
127 changes: 19 additions & 108 deletions src/bin/drawing/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,10 @@ pub struct Painter {
stencil: TextureView,
uniform_buffer: Buffer,
tile_transform_buffer: (Buffer, u64),
loaded_tiles: BTreeMap<TileId, DrawableTile>,
bind_group_layout: BindGroupLayout,
bind_group: BindGroup,
rx: crossbeam_channel::Receiver<std::result::Result<notify::event::Event, notify::Error>>,
_watcher: RecommendedWatcher,
feature_collection: Arc<RwLock<FeatureCollection>>,
temperature: crate::drawing::weather::Temperature,
}

Expand Down Expand Up @@ -161,8 +159,6 @@ impl Painter {
]
});

let feature_collection = Arc::new(RwLock::new(FeatureCollection::new(CONFIG.renderer.max_features as u32)));

let swap_chain_descriptor = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
format: wgpu::TextureFormat::Bgra8Unorm,
Expand All @@ -183,7 +179,7 @@ impl Painter {
&device,
&app_state.screen,
app_state.zoom,
std::iter::empty::<&DrawableTile>()
std::iter::empty::<&VisibleTile>()
);

let blend_pipeline = Self::create_layer_render_pipeline(
Expand Down Expand Up @@ -249,12 +245,10 @@ impl Painter {
uniform_buffer,
stencil,
tile_transform_buffer,
loaded_tiles: BTreeMap::new(),
bind_group_layout,
bind_group,
_watcher: watcher,
rx,
feature_collection,
temperature,
}
}
Expand Down Expand Up @@ -385,21 +379,22 @@ impl Painter {
device: &Device,
screen: &Screen,
z: f32,
drawable_tiles: impl Iterator<Item=&'a DrawableTile>
visible_tiles: impl Iterator<Item=&'a VisibleTile>
) -> (Buffer, u64) {
const TILE_DATA_SIZE: usize = 20;
let tile_data_buffer_byte_size = TILE_DATA_SIZE * 4 * CONFIG.renderer.max_tiles;
let mut data = vec![0f32; tile_data_buffer_byte_size];

let mut i = 0;
for dt in drawable_tiles {
let matrix = screen.tile_to_global_space(z, &dt.tile_id);
for vt in visible_tiles {
let extent = vt.extent() as f32;
let matrix = screen.tile_to_global_space(z, &vt.tile_id());
for float in matrix.as_slice() {
data[i] = *float;
i += 1;
}
for _ in 0..4 {
data[i] = dt.extent as f32;
data[i] = extent;
i += 1;
}
}
Expand Down Expand Up @@ -529,13 +524,6 @@ impl Painter {
}
}

pub fn update_styles(&mut self, zoom: f32, css_cache: &mut RulesCache) {
if css_cache.update() {
let mut feature_collection = self.feature_collection.write().unwrap();
feature_collection.load_styles(zoom, css_cache);
}
}

pub fn get_hidpi_factor(&self) -> f64 {
self.hidpi_factor
}
Expand Down Expand Up @@ -572,7 +560,7 @@ impl Painter {
&self.device,
&app_state.screen,
app_state.zoom,
self.loaded_tiles.values()
app_state.visible_tiles().values()
);
}

Expand Down Expand Up @@ -618,100 +606,18 @@ impl Painter {
device.create_texture(frame_descriptor).create_default_view()
}

fn load_tiles(&mut self, app_state: &mut AppState) {
let tile_field = app_state.screen.get_tile_boundaries_for_zoom_level(app_state.zoom, 1);

// Remove old bigger tiles which are not in the FOV anymore.
let old_tile_field = app_state.screen.get_tile_boundaries_for_zoom_level(app_state.zoom - 1.0, 2);
let key_iter: Vec<_> = self.loaded_tiles.keys().copied().collect();
for key in key_iter {
if key.z == (app_state.zoom - 1.0) as u32 {
if !old_tile_field.contains(&key) {
self.loaded_tiles.remove(&key);
}
} else {
if !tile_field.contains(&key) {
self.loaded_tiles.remove(&key);
}
}
}

app_state.tile_cache.finalize_loaded_tiles();
for tile_id in tile_field.iter() {
if !self.loaded_tiles.contains_key(&tile_id) {
app_state.tile_cache.request_tile(&tile_id, self.feature_collection.clone(), &CONFIG.renderer.selection_tags.clone());

let tile_cache = &mut app_state.tile_cache;
if let Some(tile) = tile_cache.try_get_tile(&tile_id) {

let drawable_tile = DrawableTile::load_from_tile_id(
&self.device,
tile_id,
&tile
);

self.loaded_tiles.insert(
tile_id.clone(),
drawable_tile
);

// Remove old bigger tile when all 4 smaller tiles are loaded.
let mut count = 0;
let num_x = (tile_id.x / 2) * 2;
let num_y = (tile_id.y / 2) * 2;
for tile_id in &[
TileId::new(tile_id.z, num_x, num_y),
TileId::new(tile_id.z, num_x + 1, num_y),
TileId::new(tile_id.z, num_x + 1, num_y + 1),
TileId::new(tile_id.z, num_x, num_y + 1),
] {
if !tile_field.contains(tile_id) {
count += 1;
continue;
}
if self.loaded_tiles.contains_key(tile_id) {
count += 1;
}
}
if count == 4 {
self.loaded_tiles.remove(&TileId::new(tile_id.z - 1, num_x / 2, num_y / 2));
}

// Remove old smaller tiles when all 4 smaller tiles are loaded.
for tile_id in &[
TileId::new(tile_id.z + 1, tile_id.x * 2, tile_id.y * 2),
TileId::new(tile_id.z + 1, tile_id.x * 2 + 1, tile_id.y * 2),
TileId::new(tile_id.z + 1, tile_id.x * 2 + 1, tile_id.y * 2 + 1),
TileId::new(tile_id.z + 1, tile_id.x * 2, tile_id.y * 2 + 1),
] {
self.loaded_tiles.remove(tile_id);
}
} else {
log::trace!("Could not read tile {} from cache.", tile_id);
}
}
}

let mut feature_collection = self.feature_collection.write().unwrap();
feature_collection.load_styles(app_state.zoom, &mut app_state.css_cache);
}

pub fn paint(&mut self, hud: &mut super::ui::HUD, app_state: &mut AppState) {
let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
self.load_tiles(app_state);
let feature_collection = {
let lock = self.feature_collection.clone();
let feature_collection = lock.read().unwrap();
(*feature_collection).clone()
};

let feature_collection = app_state.feature_collection().read().unwrap().clone();
self.update_uniforms(&mut encoder, &app_state, &feature_collection);
self.bind_group = Self::create_blend_bind_group(
&self.device,
&self.bind_group_layout,
&self.uniform_buffer,
&self.tile_transform_buffer
);
let num_tiles = self.loaded_tiles.len();
let num_tiles = app_state.visible_tiles().len();
let features = feature_collection.get_features();
if features.len() > 0 && num_tiles > 0 {
let frame = self.swap_chain.get_next_texture();
Expand Down Expand Up @@ -740,10 +646,14 @@ impl Painter {
app_state.screen.width as f32,
app_state.screen.height as f32
) / 2.0;
for (i, dt) in self.loaded_tiles.values_mut().enumerate() {
for (i, vt) in app_state.visible_tiles().values().enumerate() {
if !vt.is_loaded_to_gpu() {
vt.load_to_gpu(&self.device);
}
let tile_id = vt.tile_id();
let matrix = app_state.screen.tile_to_global_space(
app_state.zoom,
&dt.tile_id
&tile_id
);
let start = (matrix * &vec).xy() + &vec2(1.0, 1.0);
let s = vec2({
Expand All @@ -755,7 +665,7 @@ impl Painter {
});
let matrix = app_state.screen.tile_to_global_space(
app_state.zoom,
&(dt.tile_id + TileId::new(dt.tile_id.z, 1, 1))
&(tile_id + TileId::new(tile_id.z, 1, 1))
);
let end = (matrix * &vec).xy() + &vec2(1.0, 1.0);
let e = vec2({
Expand All @@ -772,7 +682,8 @@ impl Painter {
(e.x - s.x) as u32,
(e.y - s.y) as u32
);
dt.paint(&mut render_pass, &self.blend_pipeline, &self.noblend_pipeline, &feature_collection, i as u32);

vt.paint(&mut render_pass, &self.blend_pipeline, &feature_collection, i as u32);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ fn main() {
},
Event::EventsCleared => {
painter.update_shader();
painter.update_styles(app_state.zoom.max(14.0), &mut app_state.css_cache);
app_state.load_tiles();
painter.paint(&mut hud, &mut app_state);

app_state.stats.capture_frame();
Expand Down
Loading

0 comments on commit 6c81997

Please sign in to comment.