Fix block_on in iced_wgpu hanging Wasm builds

This commit is contained in:
Héctor Ramón Jiménez 2024-03-07 23:25:24 +01:00
parent 1bb5a1b9a2
commit ecf42b97df
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
8 changed files with 53 additions and 30 deletions

View file

@ -1,4 +1,4 @@
//! A `wasm-bindgein-futures` backend. //! A `wasm-bindgen-futures` backend.
/// A `wasm-bindgen-futures` executor. /// A `wasm-bindgen-futures` executor.
#[derive(Debug)] #[derive(Debug)]

View file

@ -6,6 +6,7 @@ use crate::core::Color;
use crate::futures::{MaybeSend, MaybeSync}; use crate::futures::{MaybeSend, MaybeSync};
use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::future::Future;
use thiserror::Error; use thiserror::Error;
/// A graphics compositor that can draw to windows. /// A graphics compositor that can draw to windows.
@ -23,7 +24,7 @@ pub trait Compositor: Sized {
fn new<W: Window + Clone>( fn new<W: Window + Clone>(
settings: Self::Settings, settings: Self::Settings,
compatible_window: W, compatible_window: W,
) -> Result<Self, Error>; ) -> impl Future<Output = Result<Self, Error>>;
/// Creates a [`Self::Renderer`] for the [`Compositor`]. /// Creates a [`Self::Renderer`] for the [`Compositor`].
fn create_renderer(&self) -> Self::Renderer; fn create_renderer(&self) -> Self::Renderer;

View file

@ -4,6 +4,7 @@ use crate::graphics::{Error, Viewport};
use crate::{Renderer, Settings}; use crate::{Renderer, Settings};
use std::env; use std::env;
use std::future::Future;
pub enum Compositor { pub enum Compositor {
TinySkia(iced_tiny_skia::window::Compositor), TinySkia(iced_tiny_skia::window::Compositor),
@ -25,22 +26,25 @@ impl crate::graphics::Compositor for Compositor {
fn new<W: Window + Clone>( fn new<W: Window + Clone>(
settings: Self::Settings, settings: Self::Settings,
compatible_window: W, compatible_window: W,
) -> Result<Self, Error> { ) -> impl Future<Output = Result<Self, Error>> {
let candidates = let candidates =
Candidate::list_from_env().unwrap_or(Candidate::default_list()); Candidate::list_from_env().unwrap_or(Candidate::default_list());
let mut error = Error::GraphicsAdapterNotFound; async move {
let mut error = Error::GraphicsAdapterNotFound;
for candidate in candidates { for candidate in candidates {
match candidate.build(settings, compatible_window.clone()) { match candidate.build(settings, compatible_window.clone()).await
Ok(compositor) => return Ok(compositor), {
Err(new_error) => { Ok(compositor) => return Ok(compositor),
error = new_error; Err(new_error) => {
error = new_error;
}
} }
} }
}
Err(error) Err(error)
}
} }
fn create_renderer(&self) -> Self::Renderer { fn create_renderer(&self) -> Self::Renderer {
@ -225,7 +229,7 @@ impl Candidate {
) )
} }
fn build<W: Window>( async fn build<W: Window>(
self, self,
settings: Settings, settings: Settings,
_compatible_window: W, _compatible_window: W,
@ -252,7 +256,8 @@ impl Candidate {
..iced_wgpu::Settings::from_env() ..iced_wgpu::Settings::from_env()
}, },
_compatible_window, _compatible_window,
)?; )
.await?;
Ok(Compositor::Wgpu(compositor)) Ok(Compositor::Wgpu(compositor))
} }

View file

@ -205,11 +205,26 @@ pub trait Application: Sized {
..crate::renderer::Settings::default() ..crate::renderer::Settings::default()
}; };
Ok(crate::shell::application::run::< let run = crate::shell::application::run::<
Instance<Self>, Instance<Self>,
Self::Executor, Self::Executor,
crate::renderer::Compositor, crate::renderer::Compositor,
>(settings.into(), renderer_settings)?) >(settings.into(), renderer_settings);
#[cfg(target_arch = "wasm32")]
{
use crate::futures::FutureExt;
use iced_futures::backend::wasm::wasm_bindgen::Executor;
Executor::new()
.expect("Create Wasm executor")
.spawn(run.map(|_| ()));
Ok(())
}
#[cfg(not(target_arch = "wasm32"))]
Ok(crate::futures::executor::block_on(run)?)
} }
} }

View file

@ -5,6 +5,7 @@ use crate::graphics::{Error, Viewport};
use crate::{Backend, Primitive, Renderer, Settings}; use crate::{Backend, Primitive, Renderer, Settings};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::future::{self, Future};
use std::num::NonZeroU32; use std::num::NonZeroU32;
pub struct Compositor { pub struct Compositor {
@ -31,8 +32,8 @@ impl crate::graphics::Compositor for Compositor {
fn new<W: compositor::Window>( fn new<W: compositor::Window>(
settings: Self::Settings, settings: Self::Settings,
compatible_window: W, compatible_window: W,
) -> Result<Self, Error> { ) -> impl Future<Output = Result<Self, Error>> {
Ok(new(settings, compatible_window)) future::ready(Ok(new(settings, compatible_window)))
} }
fn create_renderer(&self) -> Self::Renderer { fn create_renderer(&self) -> Self::Renderer {

View file

@ -6,6 +6,8 @@ use crate::graphics::compositor;
use crate::graphics::{Error, Viewport}; use crate::graphics::{Error, Viewport};
use crate::{Backend, Primitive, Renderer, Settings}; use crate::{Backend, Primitive, Renderer, Settings};
use std::future::Future;
/// A window graphics backend for iced powered by `wgpu`. /// A window graphics backend for iced powered by `wgpu`.
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Compositor { pub struct Compositor {
@ -158,17 +160,13 @@ impl Compositor {
/// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and /// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and
/// window. /// window.
pub fn new<W: compositor::Window>( pub async fn new<W: compositor::Window>(
settings: Settings, settings: Settings,
compatible_window: W, compatible_window: W,
) -> Result<Compositor, Error> { ) -> Result<Compositor, Error> {
let compositor = futures::executor::block_on(Compositor::request( Compositor::request(settings, Some(compatible_window))
settings, .await
Some(compatible_window), .ok_or(Error::GraphicsAdapterNotFound)
))
.ok_or(Error::GraphicsAdapterNotFound)?;
Ok(compositor)
} }
/// Presents the given primitives with the given [`Compositor`] and [`Backend`]. /// Presents the given primitives with the given [`Compositor`] and [`Backend`].
@ -234,7 +232,7 @@ impl graphics::Compositor for Compositor {
fn new<W: compositor::Window>( fn new<W: compositor::Window>(
settings: Self::Settings, settings: Self::Settings,
compatible_window: W, compatible_window: W,
) -> Result<Self, Error> { ) -> impl Future<Output = Result<Self, Error>> {
new(settings, compatible_window) new(settings, compatible_window)
} }

View file

@ -97,7 +97,7 @@ where
/// Runs an [`Application`] with an executor, compositor, and the provided /// Runs an [`Application`] with an executor, compositor, and the provided
/// settings. /// settings.
pub fn run<A, E, C>( pub async fn run<A, E, C>(
settings: Settings<A::Flags>, settings: Settings<A::Flags>,
compositor_settings: C::Settings, compositor_settings: C::Settings,
) -> Result<(), Error> ) -> Result<(), Error>
@ -188,7 +188,7 @@ where
}; };
} }
let compositor = C::new(compositor_settings, window.clone())?; let compositor = C::new(compositor_settings, window.clone()).await?;
let mut renderer = compositor.create_renderer(); let mut renderer = compositor.create_renderer();
for font in settings.fonts { for font in settings.fonts {

View file

@ -12,7 +12,9 @@ use crate::core::widget::operation;
use crate::core::window; use crate::core::window;
use crate::core::{Point, Size}; use crate::core::{Point, Size};
use crate::futures::futures::channel::mpsc; use crate::futures::futures::channel::mpsc;
use crate::futures::futures::{task, Future, StreamExt}; use crate::futures::futures::executor;
use crate::futures::futures::task;
use crate::futures::futures::{Future, StreamExt};
use crate::futures::{Executor, Runtime, Subscription}; use crate::futures::{Executor, Runtime, Subscription};
use crate::graphics::{compositor, Compositor}; use crate::graphics::{compositor, Compositor};
use crate::multi_window::window_manager::WindowManager; use crate::multi_window::window_manager::WindowManager;
@ -183,7 +185,8 @@ where
}; };
} }
let mut compositor = C::new(compositor_settings, main_window.clone())?; let mut compositor =
executor::block_on(C::new(compositor_settings, main_window.clone()))?;
let mut window_manager = WindowManager::new(); let mut window_manager = WindowManager::new();
let _ = window_manager.insert( let _ = window_manager.insert(