What is the fastest way to draw lines in FireMonkey? (thousandths of them)
What is the fastest way to draw lines in FireMonkey? (thousandths of them)
The fastest I've found so far is
Canvas.DrawLine(c, p, 1);
but it's still about 20 times slower than the same rendering in Chrome Canvas (JS), and twice slower than in VCL TCanvas (but which isn't antialiased)
I've tried to use a TPathData and DrawPath, but it's even slower, and "freezes" in DrawPath when there are two many lines (about 10 to 20k)
The fastest I've found so far is
Canvas.DrawLine(c, p, 1);
but it's still about 20 times slower than the same rendering in Chrome Canvas (JS), and twice slower than in VCL TCanvas (but which isn't antialiased)
I've tried to use a TPathData and DrawPath, but it's even slower, and "freezes" in DrawPath when there are two many lines (about 10 to 20k)
Eric, we know it, and after xe5, its fully and cleary understand that won't be even better no more.
ReplyDeleteSo we wait from you and your team for a better, not high priced solution (<400$) of SmartMobileStudio with minimum set of ui components for real web development, not only game's toys.
Also i assume who will release better solution - your team or Elevate team this autumn.
I put on you, just do it!
In this battle you have some advantage with using dwscript on server side - open this potential as alternative of php for delphi developers.
Simon Stuart belive me its not the case - only help in single codebase development, but they said many times on win will be only directx support......
ReplyDeleteyou can try change default Direct2D Rendering to GDIPlus
ReplyDeleteDamien Demars GDI+ (GlobalUseDirect2D set to false) is worse than everything else, almost 10 times slower than FMX Direct2D, or about 200 times slower than Chrome.
ReplyDeleteFWIW text rendering (Canvas.FillText) is on the order of 35 times slower in FMX compared to JS Canvas in Chrome.
ReplyDeleteEric Grange strange. ah Ok.. just tried it on my Win7 laptop : you're right it's terrible (20 times slower than on my vista desktop.)
ReplyDeleteEric Grange They prepared very good for your tests, want more exciting show? - just run any 3d demo with texture using (helloworld3d), and look for committed gpu mem........
ReplyDeletethere's some settings to play with in FMX.types. GlobalUseGPUCanvas give weird results but is very fast... sadly it is not documented in docwiki
ReplyDeleteDamien Demars they tried to make own 2d rasterization engine over gpu, but looks not lack yet.........
ReplyDeleteGlobalUseGPUCanvas is probably not very operational, there are glitches and anti-aliasing seems turned off with it. And while much faster, it's still much slower than Chrome.
ReplyDeleteBut but but... it's native! How can it possibly be slow?!
ReplyDeleteYou probably want to lock the canvas, draw the lines then unlock it.
ReplyDeletePaul Foster Don't Canvas.BeginScene/EndScene do that already?
ReplyDeleteEric Grange not all the cases, if paint in bitmap - you should do begin/end, if you have ready canvas - its done before - just save canvas state, set rect and paint.
ReplyDeleteAsbjørn Heid look at the sources - how long way to go (calls, checks, search by string id ect.) from your paint actions to real low end paint function....
ReplyDeleteXE5 trial here, don't have the sources. I start from a PaintBox.Canvas
ReplyDeleteEric Grange looking at the code there are no lock/unlock anymore. Quickly scouting I can't really see anything to help, perhaps you should do your canvas manipulations in a memory only bitmap and then dump that straight out to the canvas?
ReplyDeletePaul Foster Are the bitmap canvas GPU-accelerated?
ReplyDeleteI think it depends - you used to be able to change the composition mode (well, on windows anyway) from directdraw to gdi, not sure if you still can in XE5, I would have hoped so in anycase - although the smoking ape is not always very efficient with bitmaps and the GPU
ReplyDeleteIn gdi+ and direct2d modes canvas operations translated to native windows api functions:
ReplyDeletegdi+
FGPGraphics.DrawLine(FGPPen, APt1.X, APt1.y, APt2.X, APt2.y);
direct2d:
FTarget.DrawLine(D2Point(APt1.X, APt1.y), D2Point(APt2.X, APt2.y), FStrokeBrush,
ABrush.Thickness, FStrokeStyle);
In Gpu canvas do thru GPUe:
FStrokeBuilder.BuildLine(APt1, APt2, AOpacity);
*** FCanvasHelper.FillTriangles(FStrokeBuilder.Vertices, FStrokeBuilder.Colors, FStrokeBuilder.Indices,
Length(FStrokeBuilder.Vertices), Length(FStrokeBuilder.Indices) div 3);
Inc(FPrimitiveCountPerFrame);
but last one bugy on win
Also, here in fmx never was any locking states and function because its single threaded architecture,
ReplyDeleteBeginScene just do some preps and add scene count:
FClippingChangeCount := 0;
FSavingStateCount := 0;
Stroke.Thickness := 1;
Stroke.Cap := TStrokeCap.scFlat;
Stroke.Join := TStrokeJoin.sjMiter;
Stroke.Dash := TStrokeDash.sdSolid;
Stroke.Kind := TBrushKind.bkSolid;
Fill.Kind := TBrushKind.bkSolid;
SetMatrix(TMatrix.Identity);
Result := True;
EndScene just handle scene counts and send
FBitmap.BitmapChanged;
if painting was in bitmap
When need to paint in bitmap canvas in raw pixels mode, bitmap just copy from internal state to 4byte rgba mode, and then copy back to with Map/Unmap functions.
ReplyDeleteSo maybe after every line paint Map/Unmap took place - it may explain so slow paint.
Post you paint code, lets see it
And yes in xe5 still able to set gdi+ mode like in xe4, i do all my job in gdi+ because in direct2d mode some paint just dropped. Canvas.GPU was realy hope for fast graphic, but didn't yet :(
ReplyDeleteLook like should go for native paint to qt - they prepared some new scene renderer http://blog.qt.digia.com/blog/2013/09/02/new-scene-graph-renderer/?utm_source=rssutm_medium=rssutm_campaign=new-scene-graph-renderer
D2D canvas bottleneck is brush is always prepared at each drawline call. It should be done only when it has changed. Not every time.
ReplyDeleteSergionn Rad GDI+ is even slower than FMX Direct2D. So far Skia (Chrome HTML5 Canvas engine) is the fastest 2D engine I've seen by a significant margin, both in desktop and Android. You can beat it by going straight to OpenGL, but then you're pretty bare-bones in terms of features.
ReplyDeleteYou can embed Skia through node-webkit, or if you're feeling more adventurous, port Skia to Delphi or FPC (but that would be a significant undertaking).
David Berneda I tried DrawPath, but that was not only slower than DrawLine, but it would outright crash/freeze for complex paths.
ReplyDeleteOops' I mean applystroke is internally called in drawline, even if the stroke has not changed. Drawpath takes lots of time until the actual path gets rendered, lots of parsing. I miss a streamlined polyline or drawlines method. btw: android jpaint wraps around skia if I'm not wrong.
ReplyDelete