При поиске альтернатив для замены GDI я пытался протестировать производительность Delphi 2010 TDirect2DCanvas в Windows 7.
Я тестировал его, рисуя огромную полилинию с использованием Direct2D, и результат был абсурдно медленным, даже с 500 раз меньшими данными, чем сумма, которую я выполнил с тем же тестом, используя GDI (и я даже не использовал растровое изображение в качестве backbuffer в GDI, я просто обратил внимание на форму canvas напрямую).
Итак, я думаю, что:
a) Direct2D работает медленнее, чем GDI;
b) TDirect2DCanvas медленный,
c) Я делаю что-то неправильно
и, надеюсь, он в).
Проверочный код, который я написал, это:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Direct2D, D2D1;
type
TForm2 = class(TForm)
private
{ Private declarations }
FD2DCanvas: TDirect2DCanvas;
FData: array[0..50000] of TPoint;
public
procedure CreateWnd; override;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
{ Public declarations }
end;
var
Form2: TForm2;
implementation
uses utils;
{$R *.dfm}
procedure TForm2.CreateWnd;
var
i: Integer;
begin
inherited;
FD2DCanvas := TDirect2DCanvas.Create(Handle);
for i := 0 to High(FData) do begin
FData[i].X := Random(Self.ClientWidth div 2);
FData[i].Y := Random(Self.ClientHeight);
end;
end;
procedure TForm2.WMPaint(var Message: TWMPaint);
var
PaintStruct: TPaintStruct;
begin
BeginPaint(Handle, PaintStruct);
try
FD2DCanvas.BeginDraw;
try
FD2DCanvas.Polyline(FData);
finally
FD2DCanvas.EndDraw;
end;
finally
EndPaint(Handle, PaintStruct);
end;
end;
procedure TForm2.WMSize(var Message: TWMSize);
begin
if Assigned(FD2DCanvas) then begin
ID2D1HwndRenderTarget(FD2DCanvas.RenderTarget).Resize(D2D1SizeU(ClientWidth, ClientHeight));
end;
end;
end.
Кроме того, я действительно желаю рисовать длинные полилинии в реальном коде, так как система, над которой я работаю, должна нарисовать много полилиний размером ~ 2500 точек (не менее 10 тыс. из них).
Обновлено (2010-11-06)
Я узнал ранее, что Direct2D, похоже, не любит полилинии, он рисует быстрее, если вы используете много одиночных строк (2 точки полилиний).
Благодаря Chris Bensen я обнаружил, что медлительность была с большими полилиниями при использовании сглаживания. Поэтому я отключил сглаживание, как предложил Крис, и производительность от ~ 6000 мс до ~ 3500 мс для рисования линий 50 КБ.
Все еще можно улучшить, потому что Direct2D просто не обрабатывает хорошо полилинии при использовании сглаживания. С сглаживанием отключено это как раз наоборот.
Теперь время рисования с Direct2D строк 50k, если я рисую большую полилинию без сглаживания, составляет ~ 50 мс. Ницца, э-э!
Дело в том, что GDI все еще быстрее, чем Direct2D, если я рисую растровое изображение, и после этого я вернул результат в форму, он рисует в ~ 35 мс и с тем же качеством графики. И Direct2D также, похоже, уже использует backbuffer (он просто рисует, когда вызывается EndDraw()
).
Итак, можно ли это как-то улучшить, используя Direct2D по скорости?
Здесь обновленный код:
type
TArray = array[0..1] of TPoint;
PArray = ^TArray;
procedure TForm2.WMPaint(var Message: TWMPaint);
var
PaintStruct: TPaintStruct;
begin
FD2DCanvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
BeginPaint(Handle, PaintStruct);
try
FD2DCanvas.BeginDraw;
try
FD2DCanvas.Pen.Color := clRed;
FD2DCanvas.Polyline(FData);
finally
FD2DCanvas.EndDraw;
end;
finally
EndPaint(Handle, PaintStruct);
end;
end;
Кстати, даже если я использую предложение Chris о создании геометрии заранее, скорость примерно равна скорости GDI, но все же не быстрее.
Мой компьютер запускает Direct3D и OpenGL-приложения в обычном режиме и здесь выводит dxDiag: http://mydxdiag.pastebin.com/mfagLWnZ
Буду рад, если кто-нибудь сможет объяснить мне, почему эта медлительность. Пример кода очень ценится.