Experimental WebGL wgpu backend support#1096
Conversation
| use futures::{channel::mpsc, Sink}; | ||
| use std::marker::PhantomData; | ||
|
|
||
| #[cfg(not(target_arch = "wasm32"))] |
There was a problem hiding this comment.
Instead of duplication of Runtime and Tracker with the different trait bounds, but I thought that such trait aliasing may work better WYT?
|
Opening PR for review, looks like an issue with text rendering is not directly related to |
hecrj
left a comment
There was a problem hiding this comment.
Nice! Will take a proper look soon 🎉
Instead of a new example, could we instead change the existing one so it works everywhere?
|
@hecrj Actually yes I will do that, I just need to figure out alternative |
|
@hecrj made original |
|
UPD: Just a thing to consider - this example works fine with |
|
@pacmancoder Yes, I think we can remove the SPIR-V shaders altogether and use |
|
Removed spir-v shader and fixed code formatting (GH Workflow was failing in cargo fmt) |
|
@hecrj is something still blocking this PR before merge? |
|
This is great! I was about to implement the same thing before I found this. I'll take a look now as well and let you know if I find some issues. |
| #[cfg(target_arch = "wasm32")] | ||
| pub struct Clipboard; | ||
|
|
||
| #[cfg(target_arch = "wasm32")] |
There was a problem hiding this comment.
When I tried to get this to work yesterday, I added a "NullClipboard" to window_clipboard instead. We can eventually replace it with proper clipboard support for different wasm environments. I think this is cleaner than having a feature flag here, but not sure what @hecrj prefers.
Can send a pull request if my approach is more descired
hecrj
left a comment
There was a problem hiding this comment.
I took another quick glance and left some more feedback.
I still have to take a proper look and test everything! However, I'm working on a bunch of changes related to rendering and I'd like to finish that first.
| #[cfg(not(target_arch = "wasm32"))] | ||
| mod trait_aliases { | ||
| use super::*; | ||
|
|
||
| pub trait TrackerMessage: Send + 'static {} | ||
|
|
||
| impl<T> TrackerMessage for T where T: Send + 'static {} | ||
|
|
||
| pub trait TrackerMessageReceiver<Message: TrackerMessage>: | ||
| Sink<Message, Error = mpsc::SendError> + Unpin + Send + Clone + 'static | ||
| { | ||
| } | ||
|
|
||
| impl<Message: TrackerMessage, T> TrackerMessageReceiver<Message> for T where | ||
| T: Sink<Message, Error = mpsc::SendError> | ||
| + Unpin | ||
| + Send | ||
| + Clone | ||
| + 'static | ||
| { | ||
| } | ||
| } | ||
|
|
||
| #[cfg(target_arch = "wasm32")] | ||
| mod trait_aliases { | ||
| use super::*; | ||
|
|
||
| pub trait TrackerMessage: 'static {} | ||
|
|
||
| impl<T> TrackerMessage for T where T: 'static {} | ||
|
|
||
| pub trait TrackerMessageReceiver<Message: TrackerMessage>: | ||
| Sink<Message, Error = mpsc::SendError> + Unpin + Clone + 'static | ||
| { | ||
| } | ||
|
|
||
| impl<Message: TrackerMessage, T> TrackerMessageReceiver<Message> for T where | ||
| T: Sink<Message, Error = mpsc::SendError> + Unpin + Clone + 'static | ||
| { | ||
| } | ||
| } | ||
|
|
||
| pub use trait_aliases::{TrackerMessage, TrackerMessageReceiver}; |
There was a problem hiding this comment.
Are these necessary? iced_web is able to use the Runtime and, therefore, the Tracker already.
Lines 170 to 175 in 8a2a7f7
There was a problem hiding this comment.
Sadly yes, this is necessary - we use winit here with WebGL backend and it (winit) does not implement Send on its EventLoopProxy on wsam32, so yea, because of that we should lift here requirement for Send for our types too
| #[cfg(not(target_arch = "wasm32"))] | ||
| type BoxStream<'a, T> = iced_futures::futures::stream::BoxStream<'a, T>; | ||
|
|
||
| #[cfg(target_arch = "wasm32")] | ||
| type BoxStream<'a, T> = iced_futures::futures::stream::LocalBoxStream<'a, T>; |
There was a problem hiding this comment.
These are already defined in iced_futures!
Lines 43 to 69 in 8a2a7f7
|
Did you test input with this branch yet? I seem to have a bunch of issues but they are probably caused by winit. See this bug report here: rust-windowing/winit#2036 Problem is that iced still uses a custom winit branch, so it's hard to figure out what's going on is fixed upstream or not. |
@kaimast Ah... I see... Sliders in the example were working fine then I just tried to add cc @hecrj |
|
Could you rebase this on current master? iced has moved to wgpu 0.12 and it would be good to see if some of the issues are resolved. |
|
@kaimast sure, I'll try to find som spare time on this week and do the rebase |
| let event_loop = EventLoop::new(); | ||
|
|
||
| #[cfg(target_arch = "wasm32")] | ||
| let window = winit::window::WindowBuilder::new() |
There was a problem hiding this comment.
i think you can to save some cfg by doing:
let window = if cfg!(target_arch = "wasm32") {
let canvas_element = {
console_log::init_with_level(log::Level::Debug)
.expect("could not initialize logger");
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
web_sys::window()
.and_then(|win| win.document())
.and_then(|doc| doc.get_element_by_id("iced_canvas"))
.and_then(|element| element.dyn_into::<HtmlCanvasElement>().ok())
.expect("Canvas with id `iced_canvas` is missing")
};
let window = winit::window::WindowBuilder::new()
.with_canvas(Some(canvas_element))
.build(&event_loop)
.expect("Failed to build winit window")
} else {
env_logger::init();
winit::window::Window::new(&event_loop).unwrap()
};unless the Window::new() method returns separate types
|
this is very interesting. does this patch allow to run in pure wgpu, without to use html elements for the widget? |
yes |
|
Wow this is great news! To experiment with targetting webgpu, will this approach here block in future to do this? Do we need to add a webgpu feature when/if we try such a thing? |
e6ab610 to
8b0f2e6
Compare
|
@kaimast Welp, I rebased the branch to the latest master (although, some parts of the code not polished yet and need refactoring), however the problems are still here - both input handling and text rendering issues on Firefox are still present. Unfortunately, I am currently have no time to research this further, If someone still interested in this feature, you are welcome to get this branch and continue work on it |
|
I created a tiny pull request that should fix the input issues. I think it should be close to being merge-able now. |
|
Thanks, @kaimast, merged |
| let mut context = task::Context::from_waker(task::noop_waker_ref()); | ||
|
|
||
| event_loop.run_return(move |event, _, control_flow| { | ||
| event_loop.run(move |event, _, control_flow| { |
There was a problem hiding this comment.
@hecrj do you think this would break anything? It simplifies the code a lot and the winit docs says about run_return "You are strongly encouraged to use run, unless the use of this is absolutely necessary."
- Added missing `draw_cache_align_4x4` call for `brush_glyph` on wasm32 target - Added WebGL support to `integratio_wgpu` example - Fixed test.yml CI workflow - Removed spir-v shader in `integration_wgpu`; Fixed formatting - Removed redundant `BoxStream` typedef
... and hide the dependency under a `time` module in `iced_native`
It allows to clean up all the `trait_aliases` modules!
|
I made some changes here! Will explain everything first thing tomorrow! |
You can use `trunk serve` to easily compile them!
There was a problem hiding this comment.
Okay! First of all, thanks for all the efforts here. This is very cool!
As I mentioned yesterday, I made a bunch of changes, some of them quite important.
First, I have removed the iced_web subcrate completely from the repository in 825c774! iced_web has always been quite experimental and their dependencies have been outdated for a while now. Therefore, I believe it's better to move it to a different repository in the iced-rs organization. As a consequence, from now on when targetting Wasm, iced will leverage wgpu and / or glow to render into a canvas using the iced_native crate (see 26d95fd).
In my opinion, this is a better default than iced_web because it makes targetting Wasm quite easier for users. As there are fewer differences between the native stack and the web stack, all of the native widgets should work on Wasm. If you have a native iced application, chances are you can compile it to Wasm! No additional feature flags necessary! Just slap a --target wasm32-unknown-unknown to your cargo build command.
That said, the plan is to still offer iced_web as a separate crate for users that need to leverage the DOM.
The rest of the changes are relatively minor:
- I changed the
Compositoriniced_wgputo properly use WebGL limits in 7767241. - I created a new
timemodule that offers a cross-platformInstantimplementation in 87b3e03 and 83c649b. - I introduced a
MaybeSendtrait iniced_futuresin 5dab5a3, which allows us to get rid of all thetrait_aliasesmodules. - I have split the
iced_futuresexecutor implementations into differentbackendmodules in 167be45. Eachbackendshould expose the same API! - I implemented
time::everyfor thewasm_bindgenbackend in e730d97.
Finally, I have added a couple of index.html files to the todos and tour examples. You can try running them on your browser with trunk.
There are still some issues present related to rendering text. My MacBook Pro M1 displays completely mangled text in all of the examples both in Chrome and Firefox:
This seems to happen only to dynamic text, which seems to indicate there may be an issue in the cache upload logic in wgpu_glyph. Most likely related to hecrj/wgpu_glyph#78.
That said, I am pretty happy with the changes here and I think we can merge this! 🎉 We can iron out the issues in future PRs.
|
this is... awesome 😹 |



Made changes to allow the use of WebGL wgpu backend. The basic functionality works, but text rendering is still buggy - Somehow, if the initial value of the text control was changed, some parts of the text start to disappear/show artifacts.
UPD: Strange issue with text rendering is only reproducing in Firefox (v93). It is not directly related to the iced, I created an issue in
wgpu_glyphhere: hecrj/wgpu_glyph#78The current implementation provides neither
ApplicationnorSandboximplementations for this backend, and does not implement properClipboardiniced_winit, however, this should be at least some starting point.Changes list:
integration_wgpu_webglexample, based onintegration_wgpuandwgpu'shello-triangleexample (can't useintegration_wgpuexample directly because it fails with its spirv shaders on WebGL)Syncrequirement forRuntimeandTrackeriniced_futureswebglfeature toiced_wgpuwhich enableswgpu/webglClipboardiniced_winitImages
iced running inside WebGL canvas:

Text issues after changing text value:

Same example running on desktop backend:
