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
Maui in Android Overdraws even with blank project #18245
Comments
@jonmdev beyond making the overdraw colors "go away". Do you know how to measure how much fixing these actually helps? Making overdraw better helps, but does it help like 1%, 10%? How do we measure? I'm trying to gage how important this is compared to just profiling and making general C# code changes. |
Thanks for your attention @jonathanpeppers Regarding the importance, here is Android's documentation on it:
https://developer.android.com/topic/performance/hardware-accel In other words, if we are already overdrawing the entire screen in an empty project we are at 2x the number of pixels on screen per frame to begin with. Adding anything else puts us over Android's recommended amount. (Although it seems as noted below this test process has found some much bigger problems...) Maui is a GUI system by definition so letting the GUI meet expected Native performance standards and not already be overdrawn on an empty project is important I think if possible. Having reasonable redraw performance is important, but as we see below there are perhaps more significant issues still. PARTIAL SOLUTION: FOUND 1 OF THE OVERDRAWSI have found one of the two draws that is happening in the empty project of just:
ContentPage creates a backgroundColor automatically by default. If you set it with If you add Here it is with OTHER MYSTERY DRAW???This answers 1 of the two draws. What might the second draw be? It is obviously something outside my control in Maui. I can't think of anything else I can control. Is it possible to debug the Android hierarchy and see what is drawing? How many elements in Android can there be on an empty project like this? I can't imagine more than 5-20. Certainly at least one of them is drawing itself somewhere and doesn't need to be. Or perhaps this hidden element must be drawn to as we always have to draw something on each pixel of the app by default? If we must have the "hidden background object" being drawn to, then an easy solution would be to give us a method to set its PERFORMANCEHere is Android showing the project with just tweening the background color (default settings of modified demo project code as below). This is overdraw x1 and attempting to change the color of the element The colors of the bars at the bottom are explained as per: https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering The GPU is getting hammered just from this simple operation with most of the work going to red (Command Issue) and yellow (Swap Buffers). It is barely keeping up below the yellow threshold. For reference, the green threshold is 60 fps (or possible 120 fps since this is a 120 hz device?) so either way it is failing to even meet the device refresh rate. Adding a few overdraws then pushes it even mildly higher over this threshold: Thanks for any help. |
We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process. |
I found the missing overdraw. It is a white background (#FFFFFF) being applied to the DecorView, which you can only see on Android Layout viewer when it loads in "Legacy Mode" which it only does by glitch sometimes it seems (usually doesn't show you this). You have to run the following command to solve it:
FYI @jonathanpeppers if you want to fix it. I also note a small quirk (though I haven't investigated further to be sure) that when you set the ContentPage background color, you cannot null it using Maui command in Android. You similarly must get the view and SetBackground(null). Perhaps I am wrong on this. Not important to me now. What matters is it is now possible to get zero overdraw using this method. |
Android Studio's layout inspector might be a better choice to debug this. @jonmdev have you tested a Release app to see if is any different? I searched the source code for I'm not seeing any MAUI feature that the project template uses that would do
This one is on my list to look at, but I'm going on vacation soon. It might be a couple weeks when I get to this. |
I have tested and the issues occur the same whether or not you build on Release or Debug. I don't believe Maui is intentionally setting the DecorView background color to white. This could even be an Android issue. I am not sure. Either way adding the line The screencap I provided of the white DecorView was from Android Studio Layout Viewer which randomly at some points loads in "Legacy Mode" and shows this format of hierarchy which demonstrates the problem. I don't know why it loads in two different hierarchy possibilities. But when it loaded this way I could see the solution. (Usually it doesn't show the DecorView in Android Studio Layout Viewer as screencapped there.) I have also tested again and proven that yes, if you set the ContentPage's background color to anything, then set it to null after it will still overdraw subsequently unless you use the Android method SetBackground(null) to reverse it. This is the correct way to null a background in Android and is likely not being applied. This may affect other view types too (not sure didn't test other view tests). I figured out also that BoxView and Border are I believe hardware layers so will draw (contribute to overdraw) even if empty. That is normal then. I updated my demo project to the following fix demonstration:
By default it will load the project with no overdraw with one visible AbsoluteLayout with a white background, but only because of the handler changed code where:
If you comment out each of these lines you will get overdraw. I would suggest:
I think that should do it. At this point, I consider this solved for me. It has improved my app efficiency eliminating the overdraw. I am at this point much more interested if you have any comment at all on this issue. I have posted now three bug reports about it over the past 6 months with the most detailed investigations I can perform, but I have yet to receive even a single comment from anyone in your team about the issue or even suggestions on what to look at next. This is a much bigger problem than this overdraw issue, as overdraw is at least invisible (besides performance) to the user. Layout problems and glitches are very obvious to everyone. Do you have any thoughts on it? Is there any more information I can provide or anything else I should do? If you would like my .NET Android project mentioned in that thread proving the relevant functions all work as expected in Android, I am happy to share that too. Thanks for any thoughts at all. |
Fixes: dotnet#18245 Context: https://developer.android.com/studio/debug/dev-options#hardware Context: https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering#debug_overdraw Context: https://stackoverflow.com/q/6499004 There is `Debug GPU Overdraw` developer option in Android that can be enabled to see overdraw in the app. * Blue: overdrawn by 1 * Green: overdrawn by 2 * Pink: overdrawn by 3 * Red: overdrawn by 4+ The .NET MAUI project template shows `Blue` by default, in a project with nothing on the screen. A workaround is noted on dotnet#18245, but the *best* workaround would be in `Platforms\Android\MainActivity.cs`: protected override void OnCreate(Bundle? savedInstanceState) { base.OnCreate(savedInstanceState); // Clear the Window's background Window?.SetBackgroundDrawable(null); } With this change in place, the `Blue` overdraw is gone in the .NET MAUI project template. The result is .NET MAUI apps on Android should inherently use less GPU (the size of the screen), which could be noticeable on low-end devices. It could be particularly noticeable in apps that are moving into the `Red` range based on the developer's XAML & layout choices. We can make this same change in .NET MAUI's default `Maui.MainTheme` Android theme: <item name="android:windowBackground">@null</item> The default project template has a XAML style that sets the background: <Style TargetType="Page" ApplyToDerivedTypes="True"> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> </Style> So the only case this change would be noticed (wrong color), would be if: * Developer is using a `Page` with no `Background` set, and no `Background` set on the top-most layout. * Developer removed all XAML styles or is migrating a Xamarin.Forms app In this case, a developer could do one of: * Apply a `Background` to the `Page` * Extend the `Maui.MainTheme` style, but with a `Background` set
Fixes: dotnet#18245 Context: https://developer.android.com/studio/debug/dev-options#hardware Context: https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering#debug_overdraw Context: https://stackoverflow.com/q/6499004 There is `Debug GPU Overdraw` developer option in Android that can be enabled to see overdraw in the app. * Blue: overdrawn by 1 * Green: overdrawn by 2 * Pink: overdrawn by 3 * Red: overdrawn by 4+ The .NET MAUI project template shows `Blue` by default, in a project with nothing on the screen. A workaround is noted on dotnet#18245, but the *best* workaround would be in `Platforms\Android\MainActivity.cs`: protected override void OnCreate(Bundle? savedInstanceState) { base.OnCreate(savedInstanceState); // Clear the Window's background Window?.SetBackgroundDrawable(null); } With this change in place, the `Blue` overdraw is gone in the .NET MAUI project template. The result is .NET MAUI apps on Android should inherently use less GPU (the size of the screen), which could be noticeable on low-end devices. It could be particularly noticeable in apps that are moving into the `Red` range based on the developer's XAML & layout choices. We can make this same change in .NET MAUI's default `Maui.MainTheme` Android theme: <item name="android:windowBackground">@null</item> The default project template has a XAML style that sets the background: <Style TargetType="Page" ApplyToDerivedTypes="True"> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> </Style> So the only case this change would be noticed (wrong color), would be if: * Developer is using a `Page` with no `Background` set, and no `Background` set on the top-most layout. * Developer removed all XAML styles or is migrating a Xamarin.Forms app In this case, a developer could do one of: * Apply a `Background` to the `Page` * Extend the `Maui.MainTheme` style, but with a `Background` set
Description
Android publishes a guide here explaining how to Debug performance problems: https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering
Maui does not nearly perform as well as it should in Android even with the most basic setups. Likely some of this is due to bugs with overdraw.
As they show on that page, if you turn on Developer Options on an Android device, and build to it, you can also activate "Debug GPU Overdraw" mode which can show areas of overdraw on screen in real time.
Interpretation: (shown on page linked above)
MAUI OVERDRAWS EVEN IN EMPTY PROJECTS
If you even just have an empty ContentPage as the only entry in your app, by making App.xaml.cs read:
You will get an overdrawn result.
This is the default Maui project showing full screen overdraw x1 (bot icon is thus overdrawn x2):
This is the empty project with just a blank ContentPage showing as you normally see it from a user's perspective:
Here it is with overdraw mode showing it is being overdrawn:
OTHER OBJECTS
I wrote the test project as below to also test how the overdraw is affected by different objects. Any empty object with no background or coloration should not cause overdraw. Image and Layout respected this and did not increase overdraw as long as they had no background.
However, default Border and BoxView elements do increase overdraw even with no backgrounds. I suspect this is not normal behavior. I am not sure if perhaps it is due to the default stroke of the Border in its case or what the cause for the BoxView would be. Or if it is related to the underlying overdraw even in empty projects.
ISSUE
Every bit of overdraw is an entire extra layer of full screen rendering the system is doing per frame cutting down our ability to render what we actually need to by 1/4-1/3 or 1/2. If we can at least get empty projects not overdrawing this would be good and it may boost our performance considerably.
It would perhaps get us closer to our frame rates we need to hit which are currently not matching what should be expected otherwise.
I have to assume it is something intrinsic to ContentPage or the App objects as it overdraws even when they are the only things there are in the project. Thanks for any help.
Steps to Reproduce
Link to public reproduction project repository
https://github.com/jonmdev/Overdraw-Bug
Version with bug
7.0.96
Is this a regression from previous behavior?
No, this is something new
Last version that worked well
Unknown/Other
Affected platforms
Android
Did you find any workaround?
No. Tough to hit performance targets in Maui than should be expected, persistent overdraw likely contributing.
The text was updated successfully, but these errors were encountered: