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
[Spec] Slim Renderer Architecture #28
Comments
Xamarin forms wpf renderers and some of android renderers such as ButtonRenderer are fast, and we know what does "fast" mean here. |
@ysmoradi Yep! These new renderers will follow the fast renderer pattern (i.e., no wrapper view around the main view). We plan to do this for all platforms, not just Android and WPF. |
Please don't try to stay backwards compatible at all costs. This is something new. It does not have to be compatible with XF. You can make something better. |
Why not to make UI framework with own set of controls without any kind of mappings and behavioral logic fully written on c# that would be rendered with Skia graphics library? As people use strongly customized design there is no need in trying to match platform design guidelines. The only need is possibility of flexible customizations. Please correct me if i'm missing something, but i don't understand why benefit is over Renderer architecture. |
With this approach, is it possible to write a cross-platform renderer instead of the platform-specific renderer? Like mapping Button control with skia-sharp control . |
Platform renderer is a bad design. As you see, there are lots of xamarin control libs that don't support UWP due to the platform limit. I know it is very difficult to build a cross platform render. But flutter told us this is feasible. In the long term, a cross-platform renderer is the best solution. |
I think render entire app as custom 2d canvas might work seamlessly for mobile app. But it might not work for desktop app or complex app because there are so many user actions that need to be re-implemented like drag-drop, text selection, keyboard shortcut to manipulate text and so on.
|
You're absolutely right about all of this stuff, but the team is not forced to choose the only one approach. I think this all about lack of time. I mean they just need to release a "brand new" fully crossplatform ui framework in a year together with .net 6. And and it's much less risky to take good old time-tested framework as the basis. It's ok and it should be. But i believe that in long time run custom 2d canvas rendering have much more benefits and really deserves to be called "cross platform". Xamarin forms is really good thing and it has a huge progress for today. But it's time to move on. Microsoft and xamarin teams have very clever engineers and they probably considering such an approach or maybe even have some connections with http://avaloniaui.net/ as a trump card |
It could be cool to have 4-th render default grey one for Skia developers will 100% change it for sure to deliver rich design, |
If the concept of renderers is to be maintained, can thought be given to eliminating the bridge between shared UI code and renderers via
|
This is long but worth watching for some "inside baseball" on Maui. It sounds like the architecture of Maui will support both platform-rendered controls and canvas-drawn controls, and furthermore that the noble @Clancey will be continuing to work on a skia-based render set for Maui which will not only work in the MVU flavour of Maui but also for the MVVM pattern. At first glance Maui seemed like a rebranding of Forms, but on closer inspection it is a restructuring of the Forms architecture to make its layers more loosely coupled and thereby support many of the things we are asking about in this thread. Fun times ahead. |
This is slightly off topic, but is something I've wanted to ask just because of its relevance to this exact thing: How does memory work with If, for example I had a gradient control (renderer written in Skia) and over the top of that I had a semi transparent button (renderer written in Skia) would that take up twice as much memory, or is the graphics context somehow shared? How about if Skia controls overlapped non-Skia controls? I've considered implementing some fancy graphics controls in Forms using Skia before, but not understanding how the memory works has always caused enough concern that I haven't. |
@GalaxiaGuy I think using a skia control overlapped on a non-skia control, just like a winform control hosted on a wpf control. You can do this, but not the best. |
Why are so many people obsessed with Skia? A good rendering spec would be agnostic to the rendering engine used at the low level. If a particular platform renderer wants to use Skia (or Direct2D or OpenGL or whatever) that shouldn't be something the application layer should have to worry about. |
The biggest promise of XAML with WPF ages ago, was the idea of Lookless Controls where the actual graphics of the controls were deferred to templates. Xamarin Forms used XAML without this ability, and this was its weakest point, only years later partially fixed by the Drawing spec. |
Agreed! And you really need a very small number of rendering primitives to accomplish probably 99% of everything an app needs:
The XF rendering platforms have become so bloated because whenever a new type of control is added to the framework it's done with a new renderer rather than building on top of existing primitives within the framework. Yes a lot more logic would have to be moved into the framework layer, the most challenging being when it comes to items controls ( |
Uno platform is using this approach. |
That's a big goal of this change as well. Once we're on the other side of these changes the renderers will have no idea what a BindableObject or INPC means |
So a method on the renderer will get invoked by the framework whenever a |
@legistek right This basically inverts the dependencies So the renderers will just work against IButton. And then System.Maui will add a reference to the renderers project opposed to right now how the renderers have a references to Xamarin.Forms.Core I checked in a spike we have here So you can see what this might look like |
I'll be doing a stream today at 3:30 PDT time with @davidortinau and we'll be talking about the slim renderers https://www.twitch.tv/microsoftdeveloper Join us! Check it out! And ask questions! |
@PureWeen Unfortunately I missed it. Will there be a recording available on YouTube? |
That is huge, a real substantial improvement. No doubt too with the move to Maui, the complex inheritance model used in many of the renderers will be removed in favour of a more compositional approach? Going to review #66 today. |
Looking at #66, it is nice to see the slim renderers are built and invoked with 'bait-and-switch' rather than using reflection. Just a few thoughts:
|
We do have some ideas here!! We want to rework the disposal strategies a bit to hopefully resolve most if not all of the ODE exceptions. Right now we super aggressively dispose of everything in android/iOS but I'm fairly certain we can just rely on the GC to do what the GC does. If we just make sure to dereference everything and let the GC do the work that should help in a lot of these cases
This is definitely a good thing to look into as we evolve this idea. Once we reach a final design for all this we'll take a look at effects. But, yes I could see effects being obsoleted as they are intended as a way to tap into native elements without having to go full renderer. Mappers basically obsolete effects
We're still working this one out a bit. Correct me if I'm wrong @Clancey but the ActionMapper was our current approach for this yes? https://github.com/dotnet/maui/blob/slim-renderers/Maui.Core/PropertyMapper.cs#L91 |
Not exactly. So the ActionMapper is the same thing as a PropertyMapper with the exception, they are not called during the SetElement phase. So, for things like WebView, GoBack. You don't want to call that during initialization but it's still something you need to communicate with the Renderer. We already support 2 way mapping. i.e Entry. When the text value chances on the entry. the IEntry has a |
Here are some videos from our streams during Build @Clancey 's here will be more in depth I touch on them a little bit here with David |
OPPO phones manufactures phones that costs under 200$, that's way I precised the brand as an argument for good performances.
Thanks for the clarification.
Not sure raspberry Pi was made to display rich user interfaces. But even if you'd want it, i'm pretty sure the framework I've worked on shows good perfs and those devices, As I rely on caching to avoid unecessary redrawing. With my spare time I managed to have such results.. As you said : Sure Microsoft has more resources. Personnaly I see no disqualifers at using a renderer that runs smooths on all kinds of devices , that addresses the vast majority of the use cases, as a cross renderer. Especially when compared to what's actually proposed... |
Right, but they also manufacture phones which cost well above $1000.
Not the case now, but it could be, even when rendering on a 4k display. Technically, the GPU is not too bad.
My proof-of-concept library is not pixel perfect but it’s close. I’ve compared between Raspberry Pi 4 backed by GLES 3.1, and Windows 10 backed by Direct3D 12. It doesn’t use native controls. On the API surface it’s somewhat close to Skia (more specifically, I’ve tried to re-implement Direct2D), but unlike Skia and similar to D2D, it’s designed to leverage modern 3D GPUs. Under the hood it uses a third-party library called diligent engine.
Indeed, what’s proposed is just horrible. If I would choose between 2 solutions, what’s proposed and Skia, I would pick Skia no questions asked. However, even ignoring the performance, with Skia these 3 use cases (integrating 3D-rendered content, video playback, custom effects) are all very hard. Personally I don’t care about custom effects, but the software I work on often does need 3D content and/or video. |
|
Why we are not considering Silverlight like approach to drawing the controls in Framework level than, having wrappers around custom renderers (Is it because of apple's restrictions). |
I believe Flutter is a counter-example.
Strongly agree. Besides the consistency, .NET runtime currently runs on platforms which don’t have any native look at all, like embedded Linux. I would love to have officially supported GPU-targeted GUI framework which runs on top of OS kernel, bypassing X11/Wayland/XFCE desktop managers. I did it couple times myself (besides the one I linked above, for another projects I consumed nanovg instead) but an MS-supported option would be awesome. Even if I have to plug my own windowing and input support, that’s still relatively small amount of complexity compared to GPU integration, 2D rendering, and all the higher-level stuff on top of that.
You’re correct, WPF re-implemented everything on top of DirectX 9.0c. At the time, DX9 was the most compatible way to access a 3D GPU on Windows. It has a few issues probably due to limitations of D3D9 and quirks of old GPUs https://jeremiahmorrill.wordpress.com/2011/02/14/a-critical-deep-dive-into-the-wpf-rendering-system/ but still pretty darn good in practice. Only a few isolated WPF components integrate native controls, most notably the embeddable web browser. |
If you want "consistency" then you can use Flutter, Web, QT or your custom renderer or anything. What is lacking is exactly native renderers. You have to write your app at least 3 times for Windows, MacOS and Linux if you want it to be native. I know most of Windows users doesn't care that their apps looks... bad, doesn't integrate with the OS and you have to learn every app but on other platforms, especially MacOS people do care. You choose Mac because it's nice and has nice apps. Yet another cross platform renderer is useless for most... Why use this then if I can just do that in web with millions of available resources and devs... |
Desktop support is still in beta: https://flutter.dev/desktop It has a non-trivial learning curve because it includes a purposedly-built programming language, i.e. harder to find developers.
Requires a desktop environment, doesn’t work on bare metal. Electron apps tend to consume lots of memory. JavaScript is not always the best tool for the job: it’s slow, and very hard to integrate with native code, people usually do it with an embedded JSON RPC web server in the same process.
While mature, widely used, and generally good quality, the usability is not great because C++. Also, for many use cases it requires a commercial version, which is very expensive.
Extremely hard to do well. I know because I have made one: https://github.com/Const-me/Vrmac/
That was not always the case. As demonstrated by WPF, it is possible to re-create look and feel of native controls on top of a GPU-based renderer. |
Good this is stable.
You know that non of the arguments are "valid" (can't find better word). Look around, Slack, VS Code, Teams, Discord, WhatsApp etc. Most of them built with web/electron because it's fast time to market and good enough performance. If any of your argument would be true those apps would be written in C, C++ or Rust.
? does MAUI target embedded?
? MAUI also needs runtime?
I wouldn't say it's slow. Language it's not perfect either but what to do. Nothing is even close to perfect if you are working on it long enough. For now JavaScript happened to be the most universal "best tool for the job" ranging from UI, server side to embedded.
Wow, never saw anybody doing like that. Literally if you don't know C/C++ env the easiest way is to build node addon... Node is the only platform when I have integrated native code and did not want to abandon the job. You don't even need to configure anything besides your source files...
Then you should probably know how many attempts at this were made and how many are successful. Also Microsoft recreating GUI they created in WPF doesn't even count. They built it, they control every aspect of it, they can even integrate it in the OS. They built in once for Win32 with software renderer then why they could not with DirectX. I just wanted to say that there are people who would be happy for native UI library because I saw everybody who posted here wants MonoGame with UI on top. Right now if you would want to build native app for every platform with native controls, UX and integrations you would probably have to use C/C++/Rust/JS for Linux, C# for Windows but if you build for Linux then it's better to stay with C++ anyway to share logic and on MacOS integrate using Swift. If MAUI would allow to use native UI/UX but code everything/most in C# then there is an argument and a huge one. wxWidgets would be probably the only competition with that possibility and I doubt if this would be done correctly anybody would even consider it... When I found this project I got so hyped that there will be such thing supported. (Okay, if React Native Windows would have been released then there is also that but with MVU and maybe if needed some tweaks to the language we would have first contender vs JavaScript). After 2-3 years of stable Flutter I don't see people jumping to it because such platforms will always be inferior. People are more hyped for Jetpack Compose. And yet, Flutter is solving problem which is not solved as for web on mobile with low end phones isn't so performant in regions like India which is a massive market for mobile apps. Also if you think that custom rendered controls would solve all your cross platform "consistency" problems then I think that will not be the case. You will be consistently below average besides single platform of choice (at most equal with web). If you search for custom UI's (there are software e.g. in music industry which were built that way) or also with web there are problems which cannot be solved universally anyway. |
MAUI does not exist yet, we’re discussing proposed architecture here. The .NET runtime does indeed target embedded, Microsoft even ships ARM Linux binaries. They depends on Linux kernel of course, but not much else (a Unicode-related OS package).
I would like to be able to implement equivalent UX in cross-platform .NET.
Some of them were. Flutter has successfully re-implemented native controls of iOS and Android. It’s not a rocket science, just GUI design and attention to details.
Why not? They were different people with decades of time between these projects. Win32 GUI (gdi32.dll, comctl32.dll, etc.) is in large parts a legacy from 16-bit Windows 3.x.
That’s a great question. Here’s a few reasons. I don’t believe HTML5 is an optimal substrate for rich GUI apps. It was designed for documents as opposed to GUI. For instance, data binding and data templates are important parts of MS XAML platforms. With modern web, technically we have react/angular/etc., but they are implemented by third parties on top of HTML DOM. These features are fundamentally complicated, and are way more usable when provided by the platform. In business terms, this means for many projects with complicated rich GUI, HTML/Electron will take more money to develop compared to XAML. Web browsers don’t work on top of bare OS kernel, they need a desktop environment. Web browsers are huge, not all people are happy downloading 100MB installer for a chat app. 3D graphics is limited to WebGL, which is not good enough compared to appropriate GPU APIs (Direct3D on Windows, Metal on OSX and iOS, Vulkan on most modern Linuxes including Android). Hardware accelerated video is limited to HTML’s Many other use cases need to integrate with native APIs for various reasons. HTML/JavaScript doesn’t have low latency audio, has very limited support for custom input devices, doesn’t support custom peripherals, doesn’t support protected storage (Windows) or keychain services (Apple), and so on. These features are not too hard in modern .NET and don’t require writing a single line of C++, native interop is good.
The success of Electron shows that’s not what many people want. They want consistent GUI across all platforms, while keeping software development costs reasonable (e.g. avoiding C++). Another thing, among modern platforms, only OSX, iOS and Android have decent native controls. On Windows everything is in XAML nowadays, the look and feel is completely defined with these styles and templates. Note the recent 0.5 milestone of WinUI 3. On Linux there’re multiple competing desktop environments, with different native control libraries and UX conventions.
I think their main mistake was inventing Dart, instead of embedding something like .NET, Go, or JVM.
They are all solvable, look at modern web browsers or game engines. However, they are very expensive to solve well across multiple platforms, too many edge cases: DPI scaling, display rotation, right to left languages, accessibility, and many others. |
ARM is an architecture. What does it have to do with embedded? More modern than x86. Even in 2nd sentence you mention Linux...
Avalonia.
Yeah... go and try use new OS things. Oh, you can't. Best you get is "work in progress".
Oh, I forgot. Win32 GUI is legacy, doesn't change. You can work 10 years on your UI and still you won't be obsolete. Even more irrelevant.
Who cares what you believe? It has been done, it works, customers are happy enough and they decide what to we do. Not to mention more and more (all my current work) customers want web and doesn't care about desktop anymore (in general business trade). Now with COVID and remote work even more. I know companies which were "offline" first, "security" concerned but after of year of remote work they decided to go "online".
So what? I don't get this argument. XAML is designed like HTML (but worse) and now you are happy because marketing told you another.
The availability of CI, test runners and crawlers? You run everything on Windows Server? Haha.
But for .NET core they are. Not to mention PWA's or things like Neutrino which uses bundled browser with OS.
There is WebGPU incoming. It's so good people extracted it from browser and they are using it from C++/Rust for common abstraction over all platforms. If you need more performance than that probably GCed language is not enough either.
At most yet, faster than MAUI it seems. Web Audio? Web Serial? Web Usb? It for sure supports more, easily. But that are Web standards and you are talking about running on OS in things like Electron... you can have more than .NET in there. For sure this way is not limited.
What? It's not what "people" want. It's what developers want. You missed last 10 years of evolution or what? You are still on Windows XP, right? Oh no, that would be Windows 7. I know more people avoiding .NET that anything else.
Yes, aka big mistake but we have to support it. Adoption of XAML around the world perfectly shows how much people like it. "MVU" is good confirmation about this statement. And no, your world and people using C# are not examples it's good if it's the only sensible option. Also "MVU" as it people here are calling happened to be so good dev experience that everyone want's to do it.
AFAIK Gnome and KDE. Other things are just your "consistent" custom cross platform GUI.
They did but it was too slow for 120 fps.
You just given the same examples as I did. Go render some text that looks everywhere the same. Impossible because browser renders font with system font renderer and there is always some differences. Starting with layouting for fonts which different engines do differently or bugs. Game engines are even more incosistent because they do not have features like an UI framework have. You see a few bitmaps on screens and you think they are consistent but run that game on e.g. 21:9 and half of UI doesn't render because it thinks screen ended, other half tries for some reason to stretch etc. They do everything often manually so if you did not tested that it crumbles. Refund. Funny enough the best scalable, crossplatform, complex game UIs were made with web and webkit, or Coherent... |
Sorry, this discussion seems OT. Can a moderator chime in and delete some of the comments above (and this one)? |
Very welcoming community. |
C# and .NET are cross platform |
I have built several apps in xamarin forms, recently I switched to the flutter, what I instantly noticed is, ease of writing UI. I built a simple dashboard UI (refer below) within 1.5 days, if it is xamarin forms it would take me at least 3-4 days(as per my experience). Hot reload works like a charm in flutter(but most of the time it sucks in xamarin forms especially if your writing a custom renderer for a button, you cant see preview). I don't want to write a custom renderer for even simple things(Shadows, Elevations, etc), which is a tedious task, please find a way to avoid custom renderers as much as possible. Writing animations also very simple which is not the case in xamarin forms. From a backend perspective C# is pretty solid in terms of (MVVM, DI, Design patterns) hands down! |
I've been developing with Xamarin.Forms since its inception. Every client I've worked for has wanted as close to an identical UI as possible on all target platforms. Clients do not want or need native controls/widgets/views to be rendered typically. It is a rare edge case. All clients I've worked for have adopted Xamarin because existing .NET developers could use C#/.NET to build mobile apps, while being able to consume existing libraries without reinventing the wheel. Clients and developers I've spoken to want Microsoft to ditch the native UI approach, and to emulate the Flutter and UNO approach of rendering controls independently of the constraints of the platform. The majority of development time is spent trying to tweak the UI to make it look identical on both platforms for current Xamarin developers. With the release of Flutter 2.2, it is becoming increasingly difficult to rationalize further investment in MAUI until this becomes THE primary architecture for the platform. Mimicking the Flutter/UNO approach highly simplifies the development process on your end, and working prototypes are already alive and well that should be used to accelerate development. This is where developers want MS and the MAUI/Xamarin team to invest in. The holy grail for developers is for MS to emulate Flutter's architecture while giving we developers the massive advantage of being able to continue to use .NET and C# so we don't have to reinvent the wheel by rewriting libraries in an immature language like Dart. Finally, Microsoft is investing in working with Google to allow Flutter to target Windows.. MS should instead be investing in competing directly with Google by building MAUI the way its veteran developers want. If MAUI goes native UI first at launch, it will be obsolete the day it is released. If this happens, after seven years of using Xamarin/.NET to develop mobile apps, I will move on and invest in Flutter instead, because at least Google has its head on straight enough to build the tools we want and need. |
@brencode there's room in the market for different solutions and different approaches. I agree that for the most part Flutter is dominating this space as Google seems to be investing heavily in marketing (they see this as a loss leader for their cloud platform). I see that Maui and Uno are attempting to solve same issue but coming from different directions. If you want 100% consistency of layout etc, then Uno is the answer. If you want a framework for rapidly scaffolding an application, the Maui with pieces like Shell will give you that jump start - it also is the way to go if your company/customer is fixated on not using third party frameworks (I don't understand this but it does exist with some orgs) |
@brencode but MAUI will be implement also with draw controls by https://github.com/dotnet/Microsoft.Maui.Graphics.Controls |
Xamarin is very good from a backend perspective, I can quickly build enterprise architecture patterns with ease, but when it comes to UI, I need to spend a lot of time to match UI pixel perfectly with a mockup. Please focus on the UI part that's all we want. why don't you guys use Skia Sharp to draw controls on canvas which can eliminate all UI renderers. let me show a simple example, I want to create a simple round corner Entry like below. see how much code I need to write for xamarin vs flutter. Flutter way
Xamarin Way
see how much code it took to show a simple round corner text field in xamarin forms vs flutter? , this is where lot of people going away from xamarin. |
Try the .NET Maui C# MVU - Comet |
MAUI C# MVU - Comet. Also, .NET Maui will have support for drawn UI using GraphicsControl https://github.com/dotnet/Comet |
I've seen this conversation happening in a few places, and I thought I'd share my own experience (despite the fact the plural of "anecdote" is not "data"). This does not match my experience with Xamarin. The clients I've worked with have mostly fallen into two categories: Those that don't care about the UI details. Pixel perfect UI is not interesting to them compared to delivering functionality. For them, sharing business logic between platforms (and sometimes with a C# server) that can be delivered quickly is number one priority. Those that want a native looking app. Most of these have avoided Forms (for example because they want to use native navigation patterns (Android supports a lot more patterns that are a challenge on iOS)). This has started to change now with some Forms embedding and the fact that I can use effects to apply some existing native styling code to Forms controls has made that much easier. A final note that is finally getting more attention is accessibility. I've just started to scratch the surface of advanced accessibility stuff iOS and Android support natively, and being able to get access to that (even in Forms) is important. Re-implementing controls would involve a lot of work on that front. (Bit of a cheap shot, but do your designers who care about the pixels being perfect for sighted users care about the screenreader announcements being perfect for blind users?) |
Yes, accessibility is important. Issue with current platform specific controls is that they are highly coupled by design. Single control can contain behavior logic, drawing logic, user input handling and accessibility all tied to a single platform APIs. Customizing just a single aspect of a control in a multiplatform application means re-implementing same thing multiple times with vastly different APIs. Providing unified abstractions over lower-level platform APIs and building controls on top, gives multiplatform developers ability to customize controls at much lower cost. Unified APIs enable developers to implement, for example, customized drawing or customized reactions to scroll input only once, instead of writing separate implementation for each platform. Even though the cost of developing framework like this is higher in the beginning, the cost in the long run is probably smaller, as creating and maintaining loosely coupled multiplatform controls is much more cost effective for framework developers too. Look how basic Xamarin.Forms controls still are after so many years and how quickly Flutter controls are evolving. Most of Xamarin.Forms controls implement only functionality that is common on all platforms and are often missing functionality that is provided just by a single vendor. For controls build on top of unified abstractions of low-level APIs, this becomes a non-issue. Every functionality implemented in a control is instantly avaliable on all platforms. Framework controls also don't need to lag behind platform specific controls anymore, as framework can provide even controls or functionality that is not avaliable in any platform's UI framework. If there is any issue with providing accessibility features for custom-drawn controls, it is up to platform vendors to provide better APIs for this kind of multiplatform frameworks. |
WARNING: this spec is still a WIP, we're still experimenting with this concept
Description
Slim renderers architecture benefits from multi-targetting and single-project features.
Example
EntryRenderer.cs
EntryRenderer.iOS.cs
Standardization of renderers
All the default renderers will be ported to this architecture, for all platforms
Registration of renderers
The rendererRegistrar will exists on the dependency service and be accessed by
serviceCollection.Get<IRendererRegistrar>()
, allowing control to which renderer is associated to which controlInterfaces on renderers
Mapper concept
The property mapper is responsible for triggering actions in response property changes. A slim renderer itself does not subscribe to the property changes, but some declared actions are executed in response to changes.
The property mapper property of a control is
public static
and can be extended by user code.The property mapper plays no role in the feedback loop (button clicked, text entered)
TODO: discuss what to use for mapper key.
string
orobject
? It'd be nice to avoid string comparison in case when we can compare references (in case of BindableProperties)How to use legacy custom renderers
How to use third-party controls depending on old renderers
How to complement existing renderers
The new extensibility model for this architecture is based on the property mapper. When you want to add support for a new property, it only requires mapping the new property. For the property to exists, subclassing the control is necessary, but subclassing the renderer is not.
Backward Compatibility
Wether we want to keep backward compatibility with existing custom renderers, or subclasses of old renderers will influence the architecture of this
Difficulty : very high
The text was updated successfully, but these errors were encountered: