Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Software renderer, runtime renderer fallback, and core consolidation #1748

Merged
merged 64 commits into from
Mar 9, 2023

Conversation

hecrj
Copy link
Member

@hecrj hecrj commented Mar 7, 2023

This PR introduces a software renderer (#1071), implements runtime renderer fallback (#1199), and reorganizes most of the codebase.

tiny-skia renderer

I have implemented a new renderer on top of tiny-skia. tiny-skia is an absolute minimal, CPU only, 2D rendering library for the Rust ecosystem, with a focus on rendering quality, speed and binary size.

This renderer lives in the new iced_tiny_skia subcrate. Besides the mesh primitives, it has feature parity with iced_wgpu. The more complex graphical widgets like Canvas, Image, and Svg are fully supported!

Canvas support was particularly challenging. The current implementation was designed with GPUs in mind. A canvas::Frame tessellates any geometry into triangles, which GPUs can very easily render.

However, tiny-skia directly supports Bézier paths. We can use a Canvas to directly drive the tiny-skia renderer. No tessellation necessary! For this, I introduced a couple of new variants to Primitive in iced_graphics and implemented a new Frame type in iced_tiny_skia that records paths instead of tessellating the geometry with lyon.

Finally, softbuffer takes care of presentation.

iced_renderer subcrate

Now that we have a software renderer that can run anywhere, it would be great if we could have an abstraction that unifies both iced_wgpu and iced_tiny_skia and fall back to software rendering whenever a GPU-accelerated backend fails during initialization. This is what the new iced_renderer crate does!

The iced_renderer crate exposes a renderer implementation that chooses a backend at runtime and delegates accordingly. The available backends can be enabled using feature flags (currently wgpu and tiny-skia).

iced_core consolidation

The implementation of these new subcrates prompted me to reevaluate the concepts shared between different parts of the codebase.

Specifically, it seems everything needs to depend on iced_native currently. This is not ideal, since iced_native contains both core concepts (like the Widget trait) and also types that are very likely to change (like the widgets themselves). Ideally, subcrates should be able to choose a set of minimal but stable foundations to rely on. This is not currently possible in the iced ecosystem.

The solution is simple! Move the core concepts of the library to the actual iced_core subcrate! Thus, the whole Widget API now lives there (and everything related to it like renderer traits, events, layout and overlay types, etc.).

As a result, most of the subcrates only rely on iced_core now. If someone wants to implement a custom widget, they can do so without indirectly depending on all the other built-in widgets.

Also, I renamed iced_native to iced_runtime. iced_native could not originally be built for WebAssembly and I chose to name it native to differentiate it from iced_web. However, this is no longer the case. iced_native can perfectly run on a browser. Thus, the name iced_native did not make much sense anymore.

The built-in widgets have also moved to their own subcrate: iced_widget, reducing the surface of iced_runtime further. The main goal here is to make iced_runtime the official runtime providing the UserInterface type and a Command implementation (which may eventually become core concepts as well!).

Furthermore, since the widget types are now perfectly isolated, the renderer subcrates do not depend on them. This means we can make iced_widget rely on iced_renderer and set the default type for the Renderer generic type right in the struct definition. This gets rid of all the annoying widget type aliases present in the root crate! No more links to iced_native in the docs!

Finally, I have introduced a new advanced feature flag in the iced root crate. Enabling this flag exposes a new advanced module that contains concepts necessary to build custom widgets and subscriptions. As a consequence, users do not need to depend on any subcrate to leverage advanced concepts anymore. No more figuring out the correct version numbers!

Next steps

As I mentioned in #1697, this was one of the needed steps before the advanced-text branch can land on master. These changes will be merged there for now.

After this, I believe we just need to polish some rough edges (e.g. configurable line height) and we will be able to bring everything to master! 🥳

Update `resvg` in `iced_graphics`
Fix `Padding::fit` on irregular values for an axis
... with a nice little color trick :^)
Implementing this generically in our `flex` logic has an exponential
cost. Let's explore other options!
... since we are not reusing the `SwashCache`
Remove `Fill` variant for `Alignment`
@hecrj hecrj added improvement An internal improvement feature New feature or request rendering compatibility canvas labels Mar 7, 2023
@hecrj hecrj added this to the 1.0.0 milestone Mar 7, 2023
@artursapek
Copy link
Contributor

goat

@bungoboingo
Copy link
Contributor

Changes look really good!! Tested both backends & a few examples on MacOS M1 & PopOS; tiny-skia is of course quite a bit slower but pretty damn good. Nice job! 🚀 🥳

@hecrj hecrj merged commit caf2836 into advanced-text Mar 9, 2023
@hecrj hecrj deleted the feature/software-renderer branch March 9, 2023 18:05
@hecrj hecrj mentioned this pull request May 5, 2023
fenhl added a commit to midoshouse/ootr-multiworld that referenced this pull request Sep 5, 2023
In theory, iced should automatically fall back to a software renderer at
runtime if wgpu is not available (according to
iced-rs/iced#1748). In practice, for at least
one user, a test app closes silently with the wgpu feature enabled but
runs normally with it disabled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants