4
votes

I am trying to make 2D game in Delphi XE5/XE6 with FireMonkey, and I need to keep multiplatformity - I need Windows and Android build. For now, game is just drawn with lines, circles, rectangles or other polygons and I use Canvas (TPaintBox on whole screen and OnPaint event to paint). Problem is, I think that performance is extremely low, even when FireMonkey should use GPU acceleration. I made this performance test which draw 1000 rectangles on random XY positions:

procedure Paint(Canvas: TCanvas);
var
  I: Integer;
  X, Y: Single;
begin
  Canvas.BeginScene;
  Canvas.Clear($ffffffff);

  Canvas.Fill.Color := $ffff0000;
  for I := 0 to 10000 do begin
    X := Random(500);
    Y := Random(400);
    Canvas.FillRect(TRectF.Create(X, Y, X + 20, Y + 20), 0, 0, [], 1);
  end;

  Canvas.EndScene;
end;

I measured approach thru this function and I get these results:

  • Windows PC - Core2Duo 3.2GHz, GeForce 660Ti - pretty strong for such simple task - it took 20 miliseconds

  • Android Phone - HTC One X (4 core, 1 GHz, Tegra 3 CPU/GPU) - it took 50-60 milisends (not as big difference against PC, as i thought)

However I think that both devices should be able to draw not 10 000, but 100 000, or even milions rectanges (my PC with GTX 660 Ti for sure) in one frame (assuming at least 25 FPS, so in about 40 miliseconds), but I can reach this with FireMonkey, even when Delphi creators brags that it is lightnight fast and GPU accelerated. And if I replace rectangle with circle (FillArc method), when I draw 100 circles, it took about same time as 10 000 rectangles. Same with outputing letters (one-char texts). What am I doing wrong? Is there any mistake I can't see? Or it is just problem of FireMonkey? Or it is normal?

What another way I should choose than Canvas for fast drawing when I need to keep compatibility with Windows and Android?

2

2 Answers

2
votes

The Firemonkey canvas on Windows is probably not using the GPU. If you are using XE6 you can

set the global variable FMX.Types.GlobalUseGPUCanvas to true in the initialization section.

Documentation

Otherwise, in XE5 stick a TViewPort3D on your Form. Stick a TLayer3D in the TViewPort3D and change it's to Projection property to pjScreen. Stick your TPaintBox on the TLayer3D.

Another alternative could be there is an OpenGL canvas unit

You could also parallel process your loop but they will only make your test faster and maybe not your real world game (Parallel loop in Delphi)

0
votes

When you draw a circle in canvas (ie GPUCanvas) then you draw in fact around 50 small triangles. this is how GPUCanvas work. it's even worse with for exemple Rectangle with round rect. I also found that Canvas.BeginScene and Canvas.endScene are very slow operation. you can try to put form.quality to highperformance to avoid antialiasing, but i didn't see that it's change really the speed.