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)

Comments

  1. Eric, we know it, and after xe5, its fully and cleary understand that won't be even better no more.
    So 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.

    ReplyDelete
  2. 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......

    ReplyDelete
  3. you can try change default Direct2D Rendering to GDIPlus

    ReplyDelete
  4. Damien 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.

    ReplyDelete
  5. FWIW text rendering (Canvas.FillText) is on the order of 35 times slower in FMX compared to JS Canvas in Chrome.

    ReplyDelete
  6. Eric 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.)

    ReplyDelete
  7. Eric 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........

    ReplyDelete
  8. there's some settings to play with in FMX.types. GlobalUseGPUCanvas give weird results but is very fast... sadly it is not documented in docwiki

    ReplyDelete
  9. Damien Demars they tried to make own 2d rasterization engine over gpu, but looks not lack yet.........

    ReplyDelete
  10. GlobalUseGPUCanvas 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.

    ReplyDelete
  11. But but but... it's native! How can it possibly be slow?!

    ReplyDelete
  12. You probably want to lock the canvas, draw the lines then unlock it.

    ReplyDelete
  13. Paul Foster Don't Canvas.BeginScene/EndScene do that already?

    ReplyDelete
  14. Eric 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.

    ReplyDelete
  15. Asbjø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....

    ReplyDelete
  16. XE5 trial here, don't have the sources. I start from a PaintBox.Canvas

    ReplyDelete
  17. Eric 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?

    ReplyDelete
  18. Paul Foster Are the bitmap canvas GPU-accelerated?

    ReplyDelete
  19. I 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

    ReplyDelete
  20. In gdi+ and direct2d modes canvas operations translated to native windows api functions:

    gdi+
      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

    ReplyDelete
  21. Also, here in fmx never was any locking states and function because its single threaded architecture, 

    BeginScene 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

    ReplyDelete
  22. 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.
    So maybe after every line paint Map/Unmap took place - it may explain so slow paint.
    Post you paint code, lets see it

    ReplyDelete
  23. 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 :(
    Look 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

    ReplyDelete
  24. D2D canvas bottleneck is brush is always prepared at each drawline call. It should be done only when it has changed. Not every time.

    ReplyDelete
  25. Sergionn 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.
    You 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).

    ReplyDelete
  26. David Berneda I tried DrawPath, but that was not only slower than DrawLine, but it would outright crash/freeze for complex paths.

    ReplyDelete
  27. Oops' 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

Post a Comment