mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Fix WASM loading (#320)
* Rename send to send_back and remove use of Promise * Fix bug where wasm loading fails * Bump memory for multi threading
This commit is contained in:
parent
a9dc4a066b
commit
5146e6a36d
@ -21,7 +21,7 @@ const MUNICH_COORDS: TileCoords = TileCoords {
|
||||
pub struct DummyContext;
|
||||
|
||||
impl Context for DummyContext {
|
||||
fn send<T: IntoMessage>(&self, _message: T) -> Result<(), SendError> {
|
||||
fn send_back<T: IntoMessage>(&self, _message: T) -> Result<(), SendError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ pub struct HeadlessContext {
|
||||
}
|
||||
|
||||
impl Context for HeadlessContext {
|
||||
fn send<T: IntoMessage>(&self, message: T) -> Result<(), SendError> {
|
||||
fn send_back<T: IntoMessage>(&self, message: T) -> Result<(), SendError> {
|
||||
self.messages.deref().borrow_mut().push(message.into());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ pub enum SendError {
|
||||
/// Allows sending messages from workers to back to the caller.
|
||||
pub trait Context: 'static {
|
||||
/// Send a message back to the caller.
|
||||
fn send<T: IntoMessage>(&self, message: T) -> Result<(), SendError>;
|
||||
fn send_back<T: IntoMessage>(&self, message: T) -> Result<(), SendError>;
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@ -190,7 +190,7 @@ pub struct SchedulerContext {
|
||||
}
|
||||
|
||||
impl Context for SchedulerContext {
|
||||
fn send<T: IntoMessage>(&self, message: T) -> Result<(), SendError> {
|
||||
fn send_back<T: IntoMessage>(&self, message: T) -> Result<(), SendError> {
|
||||
self.sender
|
||||
.send(message.into())
|
||||
.map_err(|_e| SendError::Transmission)
|
||||
@ -282,7 +282,7 @@ pub mod tests {
|
||||
pub struct DummyContext;
|
||||
|
||||
impl Context for DummyContext {
|
||||
fn send<T: IntoMessage>(&self, _message: T) -> Result<(), SendError> {
|
||||
fn send_back<T: IntoMessage>(&self, _message: T) -> Result<(), SendError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ impl<T: RasterTransferables, C: Context> ProcessRasterContext<T, C> {
|
||||
image_data: RgbaImage,
|
||||
) -> Result<(), ProcessRasterError> {
|
||||
self.context
|
||||
.send(T::LayerRaster::build_from(*coords, layer_name, image_data))
|
||||
.send_back(T::LayerRaster::build_from(*coords, layer_name, image_data))
|
||||
.map_err(|e| ProcessRasterError::Processing(Box::new(e)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ pub fn fetch_raster_apc<K: OffscreenKernel, T: RasterTransferables, C: Context +
|
||||
log::error!("{e:?}");
|
||||
|
||||
context
|
||||
.send(<T as RasterTransferables>::LayerRasterMissing::build_from(
|
||||
.send_back(<T as RasterTransferables>::LayerRasterMissing::build_from(
|
||||
coords,
|
||||
))
|
||||
.map_err(ProcedureError::Send)?;
|
||||
|
||||
@ -125,7 +125,7 @@ impl<T: VectorTransferables, C: Context> ProcessVectorContext<T, C> {
|
||||
|
||||
fn tile_finished(&mut self, coords: &WorldTileCoords) -> Result<(), ProcessVectorError> {
|
||||
self.context
|
||||
.send(T::TileTessellated::build_from(*coords))
|
||||
.send_back(T::TileTessellated::build_from(*coords))
|
||||
.map_err(|e| ProcessVectorError::SendError(e))
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ impl<T: VectorTransferables, C: Context> ProcessVectorContext<T, C> {
|
||||
layer_name: &str,
|
||||
) -> Result<(), ProcessVectorError> {
|
||||
self.context
|
||||
.send(T::LayerMissing::build_from(*coords, layer_name.to_owned()))
|
||||
.send_back(T::LayerMissing::build_from(*coords, layer_name.to_owned()))
|
||||
.map_err(|e| ProcessVectorError::SendError(e))
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ impl<T: VectorTransferables, C: Context> ProcessVectorContext<T, C> {
|
||||
layer_data: tile::Layer,
|
||||
) -> Result<(), ProcessVectorError> {
|
||||
self.context
|
||||
.send(T::LayerTessellated::build_from(
|
||||
.send_back(T::LayerTessellated::build_from(
|
||||
*coords,
|
||||
buffer,
|
||||
feature_indices,
|
||||
@ -162,7 +162,7 @@ impl<T: VectorTransferables, C: Context> ProcessVectorContext<T, C> {
|
||||
geometries: Vec<IndexedGeometry<f64>>,
|
||||
) -> Result<(), ProcessVectorError> {
|
||||
self.context
|
||||
.send(T::LayerIndexed::build_from(
|
||||
.send_back(T::LayerIndexed::build_from(
|
||||
*coords,
|
||||
TileIndex::Linear { list: geometries },
|
||||
))
|
||||
|
||||
@ -151,7 +151,7 @@ pub fn fetch_vector_apc<K: OffscreenKernel, T: VectorTransferables, C: Context +
|
||||
log::error!("{e:?}");
|
||||
for to_load in &fill_layers {
|
||||
context
|
||||
.send(<T as VectorTransferables>::LayerMissing::build_from(
|
||||
.send_back(<T as VectorTransferables>::LayerMissing::build_from(
|
||||
coords,
|
||||
to_load.to_string(),
|
||||
))
|
||||
|
||||
@ -59,6 +59,7 @@ if (multithreaded) {
|
||||
let baseConfig = {
|
||||
platform: "browser",
|
||||
bundle: true,
|
||||
minify: release,
|
||||
assetNames: "assets/[name]",
|
||||
define: {
|
||||
WEBGL: `${webgl}`,
|
||||
|
||||
@ -25,7 +25,7 @@ export const startMapLibre = async (wasmPath: string | undefined, workerPath: st
|
||||
preventDefaultTouchActions();
|
||||
|
||||
if (MULTITHREADED) {
|
||||
const MEMORY = 209715200; // 200MB
|
||||
const MEMORY = 900 * 1024 * 1024; // 900 MB
|
||||
const PAGES = 64 * 1024;
|
||||
|
||||
const memory = new WebAssembly.Memory({initial: 1024, maximum: MEMORY / PAGES, shared: true})
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import * as maplibre from "../wasm/maplibre"
|
||||
|
||||
type MessageData = {type: 'wasm_init', module: WebAssembly.Module, memory: WebAssembly.Memory}
|
||||
| {type: 'call', work_ptr: number}
|
||||
| {type: 'pool_call', work_ptr: number}
|
||||
|
||||
let initialised: Promise<maplibre.InitOutput> = null
|
||||
|
||||
@ -17,7 +17,7 @@ onmessage = async (message: MessageEvent<MessageData>) => {
|
||||
const data = message.data;
|
||||
const module = data.module;
|
||||
const memory = data.memory;
|
||||
const initialised = maplibre.default(module, memory).catch(err => {
|
||||
initialised = maplibre.default(module, memory).catch(err => {
|
||||
// Propagate to main `onerror`:
|
||||
setTimeout(() => {
|
||||
throw err;
|
||||
@ -25,10 +25,8 @@ onmessage = async (message: MessageEvent<MessageData>) => {
|
||||
// Rethrow to keep promise rejected and prevent execution of further commands:
|
||||
throw err;
|
||||
});
|
||||
} else if (type === 'call') {
|
||||
} else if (type === 'pool_call') {
|
||||
const work_ptr = message.data.work_ptr; // because memory is shared, this pointer is valid in the memory of the main thread and this worker thread
|
||||
// This will queue further commands up until the module is fully initialised:
|
||||
await initialised;
|
||||
|
||||
const process_data: (msg: any) => Promise<void> = maplibre["multithreaded_process_data"]
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use js_sys::Promise;
|
||||
use rand::prelude::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::Worker;
|
||||
@ -17,8 +16,10 @@ extern "C" {
|
||||
fn new_worker() -> JsValue;
|
||||
}
|
||||
|
||||
pub type PinnedFuture = std::pin::Pin<Box<(dyn std::future::Future<Output = ()> + 'static)>>;
|
||||
|
||||
type NewWorker = Box<dyn Fn() -> Result<Worker, WebError>>;
|
||||
type Execute = Box<dyn (FnOnce() -> Promise) + Send>;
|
||||
type Execute = Box<dyn (FnOnce() -> PinnedFuture) + Send>;
|
||||
|
||||
pub struct WorkerPool {
|
||||
new_worker: NewWorker,
|
||||
@ -44,7 +45,7 @@ pub struct Work {
|
||||
}
|
||||
|
||||
impl Work {
|
||||
pub fn execute(self) -> Promise {
|
||||
pub fn execute(self) -> PinnedFuture {
|
||||
(self.func)()
|
||||
}
|
||||
}
|
||||
@ -139,13 +140,16 @@ impl WorkerPool {
|
||||
///
|
||||
/// Returns any error that may happen while a JS web worker is created and a
|
||||
/// message is sent to it.
|
||||
pub fn execute(&self, f: impl (FnOnce() -> Promise) + Send + 'static) -> Result<(), WebError> {
|
||||
pub fn execute(
|
||||
&self,
|
||||
f: impl (FnOnce() -> PinnedFuture) + Send + 'static,
|
||||
) -> Result<(), WebError> {
|
||||
let worker = self.worker()?;
|
||||
let work = Work { func: Box::new(f) };
|
||||
let work_ptr = Box::into_raw(Box::new(work));
|
||||
match worker.post_message(
|
||||
&js_sys::Object::from_entries(&js_sys::Array::of2(
|
||||
&js_sys::Array::of2(&JsValue::from("type"), &js_sys::JsString::from("call")),
|
||||
&js_sys::Array::of2(&JsValue::from("type"), &js_sys::JsString::from("pool_call")),
|
||||
&js_sys::Array::of2(&JsValue::from("work_ptr"), &JsValue::from(work_ptr as u32)),
|
||||
))
|
||||
.expect("can not fail"),
|
||||
|
||||
@ -36,12 +36,7 @@ impl Scheduler for WebWorkerPoolScheduler {
|
||||
T: Future<Output = ()> + 'static,
|
||||
{
|
||||
self.pool
|
||||
.execute(move || {
|
||||
wasm_bindgen_futures::future_to_promise(async move {
|
||||
future_factory().await;
|
||||
Ok(JsValue::undefined())
|
||||
})
|
||||
})
|
||||
.execute(move || Box::pin(future_factory()))
|
||||
.map_err(|e| ScheduleError::Scheduling(Box::new(e)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
use maplibre::io::apc::CallError;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
|
||||
use crate::{platform::multithreaded::pool::Work, JSError};
|
||||
|
||||
/// Entry point invoked by the worker.
|
||||
#[wasm_bindgen]
|
||||
pub async fn multithreaded_process_data(work_ptr: *mut Work) -> Result<(), JSError> {
|
||||
let work = unsafe { Box::from_raw(work_ptr) };
|
||||
JsFuture::from(work.execute())
|
||||
.await
|
||||
.map_err(|_e| CallError::Schedule)?;
|
||||
let work: Box<Work> = unsafe { Box::from_raw(work_ptr) };
|
||||
work.execute().await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ pub struct PassingContext {
|
||||
}
|
||||
|
||||
impl Context for PassingContext {
|
||||
fn send<T: IntoMessage>(&self, message: T) -> Result<(), SendError> {
|
||||
fn send_back<T: IntoMessage>(&self, message: T) -> Result<(), SendError> {
|
||||
let message = message.into();
|
||||
let tag = if WebMessageTag::LayerRaster.dyn_clone().as_ref() == message.tag() {
|
||||
&WebMessageTag::LayerRaster
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user