Repository navigation
Drawing text is too slow #61
Description
Activity
Yeah, we've got a fair amount of performance work to do...
There's probably a fair amount of low hanging fruit....I can take ~15% pretty easily from
InternalPath.FindIntersection(in Segment source, in Segment target)by moving the method to theSegmentstruct which allows inlining but I think we need to do a proper review. @tocsoft is there anything you particularly would like another pair of eyes on?the find intersections stuff is definitely the hottest path in the whole of our vector drawing so anything to help in there would be awesome.... other things to consider is our whole rasterization algorithm is rather naive and there might be changes we can make in there instead that could reduce the amount of can lines we perform (by default we process each pixel I think 16 times while anti-aliasing)
@tocsoft I've managed to take 25% off the processing time for that method so far. Having a look at some intrinsics for additional boosts.
I have a question regarding the double precision code. My current implementation is using single precision and all the tests are passing. Is there a test I can run to prove I still require double precision?
@tzachshabtay I just had a quick look at your code and it looks like you are rendering the string without antialiasing in the System.Drawing version. Our default options have antialiasing enabled. Could you turn that off and then please compare performance.
Ah, turned off antialiasing, I'm now getting between 25-65ms (median: 45ms).
So, great improvement, still too slow.
FindIntersectionsWithOrientationis still the bottleneck.We'll have a look but there's no guarantee that we will be able to make dramatic improvements any time soon. There's a lot to assess.
@tocsoft @JimBobSquarePants we don't need a generic intersection finding algorithm, since one of the lines is always horizontal. Additionally, the intersection finding should be a bulk operation (faster by default, even faster if SIMD optimized).
#7 is here to deal with this, I don't think it's worth to do other optimizations before implementing that.
@antonfirsov The current implementation I have is based on DirectX Maths which has an SSE path I can quite easily implement if I know that I can carry on with single precision. I've not done any work adding that and won't until I can derive a test to ensure my implementation can replace the current double precision one.
I'm really scratching the surface with the API at the moment so I wasn't aware of #7
I'm curious why we even need to find intersections when rendering text
@tzachshabtay we need to rasterize the polygon. The current naive approach is to start by calculating
line x lineintersections for each horizontal pixel line crossing the polygon lines. (@tocsoft correct me if I'm wrong.) We'd be more than happy to accept a community contribution improving this.Reacted by Tzach ShabtayThat's correct except we do it multiple times per line to create a series of subpixels which we use for antialias purposes.
Current (25% faster) segment intersection impl.
public Vector2 FindIntersection(in Segment target) - addedhelp wantedExtra attention is neededExtra attention is needed
on Sep 2, 2020 If I recall correctly I did try profiling this stuff (it was a little while ago) after this was applied and it did nicely help offset that as the point of contention.
Code by @JimBobSquarePants seemed to work fine and help. However after implementing it the next bottleneck is the pixel blending (which lives over in the core library rather than in Drawing). I think the blender would need to be looked at next... just changing the rendering algorithm will not fix the problem we still need up to route through that blending code used by the brushes.
Prerequisites
DEBUGandRELEASEmode(Wasn't sure if this should go here or in
SixLabors.Fonts)I'm trying to convert a working game engine from
system.drawing, but my game engine (which usually hits 60 FPS without a problem) shows less than 10 FPS, due to a debug label which shows the cursor position and constantly updates as the cursor moves.When I measured the text rendering time, I saw that
ImageSharp.Drawingtakes somewhat between 90ms and 170ms (median: 134ms) to render the text, andsystem.drawingtakes ~0.3ms for rendering the text, so somewhat between x300 and x400 better performance.Here's the analysis from xamarin profiler:

FindIntersectionWithOrientationseems to be the biggest bottleneck: I'm completely ignorant when it comes to text rendering, I'm curious why we even need to find intersections when rendering text, I always imagined a glyph is just a series of path instructions that you map to size and render as is.Steps to Reproduce
DemoDesktopfrom here: https://github.com/tzachshabtay/MonoAGS/tree/ImageSharp (using Visual Studio for Mac)If you want to compare to the
system.drawingversion, checkout the master branch, the equivalent line is here:https://github.com/tzachshabtay/MonoAGS/blob/cadd7acbef6b1a97e47166681ba7e349074c4b47/Source/Engine/AGS.Engine.Desktop/Drawing/DesktopBitmapTextDraw.cs#L93
System Configuration
Mono JIT compiler version 6.4.0.208 (2019-06/07c23f2ca43 Wed Oct 2 04:52:23 EDT 2019)