Add a pool which can tesselate in a separate thread

This commit is contained in:
Maximilian Ammann 2021-12-29 21:49:26 +01:00
parent 0316991558
commit 45fa50962e
7 changed files with 153 additions and 11 deletions

View File

@ -1,3 +1,4 @@
use mapr::io::pool::Pool;
use mapr::main_loop;
use winit::event_loop::EventLoop;
use winit::window::WindowBuilder;
@ -11,5 +12,12 @@ fn main() {
.build(&event_loop)
.unwrap();
pollster::block_on(main_loop::setup(window, event_loop));
let io_tile_pool = Pool::new();
let main_tile_pool = io_tile_pool.clone();
std::thread::spawn(move || {
io_tile_pool.run_loop();
});
pollster::block_on(main_loop::setup(window, event_loop, main_tile_pool));
}

View File

@ -1 +1,25 @@
pub mod pool;
pub mod static_database;
#[derive(Clone, Copy, Debug)]
pub struct TileCoords {
pub x: u32,
pub y: u32,
pub z: u8,
}
impl TileCoords {
fn hash(&self) -> u32 {
self.x + self.y + self.z as u32
}
}
impl Into<TileCoords> for (u32, u32, u8) {
fn into(self) -> TileCoords {
TileCoords {
x: self.0,
y: self.1,
z: self.2,
}
}
}

104
src/io/pool.rs Normal file
View File

@ -0,0 +1,104 @@
use crate::io::{static_database, TileCoords};
use crate::render::shader_ffi::GpuVertexUniform;
use crate::tesselation::{IndexDataType, Tesselated};
use lyon::tessellation::VertexBuffers;
use std::collections::VecDeque;
use std::io::Cursor;
use std::sync::{Arc, Mutex};
use vector_tile::parse_tile_reader;
use vector_tile::tile::Tile;
#[derive(Clone)]
pub struct TesselatedTile {
coords: TileCoords,
geometry: VertexBuffers<GpuVertexUniform, IndexDataType>,
}
#[derive(Clone)]
pub struct Pool {
requests: WorkQueue<TileCoords>,
responses: WorkQueue<TesselatedTile>,
}
impl Pool {
pub fn new() -> Self {
Self {
requests: WorkQueue::new(),
responses: WorkQueue::new(),
}
}
pub fn fetch(&self, coords: TileCoords) {
self.requests.push(coords);
}
pub fn get_available(&self) -> Vec<TesselatedTile> {
self.responses.pop_all()
}
pub fn run_loop(&self) {
while let Some(coords) = self.requests.pop() {
if let Some(file) = static_database::get_tile(&coords) {
let tile = parse_tile_reader(&mut Cursor::new(file.contents()))
.expect("failed to load tile");
let mut geometry: VertexBuffers<GpuVertexUniform, IndexDataType> =
VertexBuffers::new();
let (_tile_stroke_range, _tile_fill_range) = {
(
tile.tesselate_stroke(&mut geometry, coords.hash()),
tile.tesselate_fill(&mut geometry, coords.hash()),
)
};
self.responses.push(TesselatedTile { coords, geometry });
}
}
}
}
#[derive(Clone)]
struct WorkQueue<T: Send> {
inner: Arc<Mutex<VecDeque<T>>>,
}
impl<T: Send> WorkQueue<T> {
fn new() -> Self {
Self {
inner: Arc::new(Mutex::new(VecDeque::new())),
}
}
fn pop_all(&self) -> Vec<T> {
let mut result = Vec::new();
if let Ok(mut queue) = self.inner.lock() {
while let Some(element) = queue.pop_front() {
result.push(element);
}
} else {
panic!("locking failed");
}
result
}
fn try_pop(&self) -> Option<T> {
let mut queue = self.inner.try_lock().ok()?;
queue.pop_front()
}
fn pop(&self) -> Option<T> {
if let Ok(mut queue) = self.inner.lock() {
queue.pop_front()
} else {
panic!("locking failed");
}
}
fn push(&self, work: T) -> usize {
if let Ok(mut queue) = self.inner.lock() {
queue.push_back(work);
queue.len()
} else {
panic!("locking failed");
}
}
}

View File

@ -1,6 +1,7 @@
use std::concat;
use std::env;
use crate::io::TileCoords;
use include_dir::{include_dir, Dir, File};
static TILES: Dir = include_dir!("$OUT_DIR/extracted-tiles");
@ -9,8 +10,8 @@ pub fn get_source_path() -> &'static str {
concat!(env!("OUT_DIR"), "/extracted-tiles")
}
pub fn get_tile(x: u32, y: u32, z: u32) -> Option<&'static File<'static>> {
TILES.get_file(format!("{}/{}/{}.{}", z, x, y, "pbf"))
pub fn get_tile(coords: &TileCoords) -> Option<&'static File<'static>> {
TILES.get_file(format!("{}/{}/{}.{}", coords.z, coords.x, coords.y, "pbf"))
}
#[cfg(test)]
@ -19,7 +20,7 @@ mod tests {
#[test]
fn test_tiles_available() {
assert!(get_tile(0, 0, 0).is_none()); // World overview
assert!(get_tile(2179, 1421, 12).is_some()); // Maxvorstadt Munich
assert!(get_tile((0, 0, 0).into()).is_none()); // World overview
assert!(get_tile((2179, 1421, 12).into()).is_some()); // Maxvorstadt Munich
}
}

View File

@ -3,12 +3,15 @@ use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEve
use winit::event_loop::{ControlFlow, EventLoop};
use crate::input::InputHandler;
use crate::io::pool::Pool;
use crate::platform::Instant;
use crate::render::state::State;
pub async fn setup(window: winit::window::Window, event_loop: EventLoop<()>) {
pub async fn setup(window: winit::window::Window, event_loop: EventLoop<()>, pool: Pool) {
info!("== mapr ==");
pool.fetch((2179, 1421, 12).into());
let mut input = InputHandler::new();
let mut state = State::new(&window).await;
@ -55,7 +58,7 @@ pub async fn setup(window: winit::window::Window, event_loop: EventLoop<()>) {
let now = Instant::now();
let dt = now - last_render_time;
last_render_time = now;
input.update_state( &mut state, dt);
input.update_state(&mut state, dt);
match state.render() {
Ok(_) => {}
// Reconfigure the surface if lost

View File

@ -19,7 +19,7 @@ use crate::io::static_database;
use crate::platform::{COLOR_TEXTURE_FORMAT, MIN_BUFFER_SIZE};
use crate::render::{camera, shaders};
use crate::tesselation::tile_mask::TileMask;
use crate::tesselation::Tesselated;
use crate::tesselation::{IndexDataType, Tesselated};
use crate::util::measure::Measure;
use super::piplines::*;
@ -89,7 +89,7 @@ pub struct State {
tile_mask_range: Range<u32>,
tile_mask_instances: wgpu::Buffer,
pub(crate) camera: camera::Camera,
pub camera: camera::Camera,
projection: camera::Projection,
pub scene: SceneParams,
@ -153,7 +153,7 @@ impl State {
);
let tile = parse_tile_reader(&mut Cursor::new(
static_database::get_tile(2179, 1421, 12)
static_database::get_tile(&(2179, 1421, 12).into())
.unwrap()
.contents(),
))
@ -172,7 +172,7 @@ impl State {
// tile right to it
let tile = parse_tile_reader(&mut Cursor::new(
static_database::get_tile(2180, 1421, 12)
static_database::get_tile(&(2180, 1421, 12).into())
.unwrap()
.contents(),
))

View File

@ -10,6 +10,8 @@ use std::ops::Range;
const DEFAULT_TOLERANCE: f32 = 0.02;
pub type IndexDataType = u32; // Must match INDEX_FORMAT
pub trait Tesselated<OutputIndex: std::ops::Add> {
fn tesselate_stroke(
&self,