-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Use double for compositor types #11768
Conversation
break; | ||
case RefreshVisualizerState.Pending: | ||
contentVisual.Opacity = 1; | ||
contentVisual.RotationAngle = _startingRotationAngle + (float)(2 * Math.PI); | ||
if (IsPullDirectionVertical) | ||
{ | ||
offset = new Vector3(0, (float)(_interactionRatio * (IsPullDirectionFar ? -1 : 1) * root.Bounds.Height), 0); | ||
offset = new Vector3D(0, (float)(_interactionRatio * (IsPullDirectionFar ? -1 : 1) * root.Bounds.Height), 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is still float cast, same for line 270
You can test this PR using the following package version. |
Just wanted to ask the question since it appears we are effectively replacing floats (4 bytes) for doubles (8 bytes), what is the anticipated impact on performance of this change on desktops along with smaller/embedded devices? |
Extra 120 bytes per visual |
I'm a little-bit confused by this.
Fundamentally, the rendering system I thought shouldn't care what is outside it's viewport bounds. The layout system should handle all measuring in double precision and by the time it gets to the rendering layer you basically only worry about what is in the viewport. Obviously, what is in the viewport is very small and float is just fine. I'm worried there is a deeper architectural problem we are missing here. Other systems don't require double in the rendering layer to avoid these issues AFAIK. Disclaimer: I have little knowledge of this area and the above is just my assumption of how things should work. UWP/WinUI works just fine though with single floating point precision. |
@robloo
It is cast back to float in the Skia code.
That repro with a button and huge margin doesn't work in UWP and most of frameworks: https://github.com/AvaloniaUI/Avalonia/pull/11768/files#diff-307943b78ddd2a40548b0dc76bfc01a8875b2b505ca85d3007f018faa1f4ba42 Assumingly same would go with enormously huge lists as well, but this one is harder to reproduce on other frameworks. |
Also, Steven's comment about smooth vs logical scrolling should clarify why some controls like DataGrid could handle it with floats #11641 (comment). |
Ah, the explanation for DataGrid answers a question how that could work. It seemed like something was still missing there. It sounds like you have talked this over in detail. Hopefully there are no major performance impacts from the overhead and loss of hardware accelerated types. I'll keep quiet otherwise though. |
It's about computations that happen before passing any commands to the GPU. I. e. consider the following example: <ScrollViewer>
<StackPanel>
<Button Margin="0 1000000000 0 0">0</Button>
<Button>1</Button>
</StackPanel>
</ScrollViewer> Once the ScrollViewer is scrolled down completely the first Button transform would be
Offsets can be specified outside of the layout system, e. g. <Border RenderTransform="translate(0, 10000000100)">
<Border RenderTransform="translate(0, -10000000000)">
<Button Content="Foo"/>
</Border>
</Border> should render the Button at 100px offset, not at 0px offset. Visual offsets can be animated on the render thread too, so we need to preserve precision there. You can consider this to be "offloading layout tasks to the render thread" if you want, it's still more efficient than doing such computations on the busy UI thread.
WPF passes double precision numbers to UCE, so various transform computations happen on the compositor side too. We need compatibility with pre-existing WPF code and concepts, not with "majority of core rendering systems" when it comes to processing the visual tree. |
@kekekeks Thanks for the detailed explanation.
That makes sense to me and is what I would normally expect. Layout calculation must use double precision due to the math and precision. But by the time it gets to Skia and in turn the GPU the range of numbers is much, much smaller.
The RenderTransform is a good example of why not everything can be done in the layout system before rendering. However, requiring bounds less than 10 billion might be perfectly reasonable ;) RenderTransform usage in practice is much smaller than that. It does sound like layout calculations can be done in a slightly different way (before actual rendering) to avoid this issue. The composition rendering system is really doing the last step of layout itself before handing off to Skia and the GPU. I also suspect WinUI does some tricks here we could learn from in the future (they get a lot wrong too though with Point, Rect, etc. being single precision). But if this strategy worked for WPF I guess there is precedent and if Avalonia's composition renderer needs to support this for WPF compatibility that also makes sense. |
Layout calculations are done using
WinUI also has the problem that prompted this change actually. Try creating an |
Can't believe that listbox performance issue leads to such a big change. 😱 |
My main concern was this is bringing pretty big memory impacts to all visuals and potentially performance degradations for what I thought was an edge case, but maybe showing millions of items at a time or having visuals offset half a billion units is more common than I thought. |
Note that 0.10.x renderers are using double precision. The single precision was introduced as a part of UWP composition API clone. |
I just noticed that avalonia has its own Vector3D type. I'm curious if the motivation for this was because system.numerics only supports floats for Vector3. I was looking at this issue here dotnet/runtime#24168 and from I can tell, there are complexities involved due to support for SIMD instructions on double types which can impact performance with hardware acceleration. Does anyone here know if the avalonia Vector3D can take advantage of possible hardware acceleration? From the quick glance I saw in the source, it seems like just an ordinary struct doing the usual mathematical operations that I would expect on a vector type (contrasted with the system.numerics.Vector3 which seems to have a bit more going on). Please excuse my ignorance on this matter. |
See #11641 (comment) |
We need to use
double
values for visuals since we have problems with precision otherwise.Unfortunately it's a breaking change and we can't keep complete compatibility with RC1. Source code should be compatible with recompilation since implicit conversions from Vector2/Vector3 to Vector/Vector3D were added.
See:
#11641
AvaloniaUI/Avalonia.Controls.TreeDataGrid#176