GDI に代わる代替手段を探している間、私はWindows 7 でDelphi の 2010 TDirect2DCanvasのパフォーマンスをテストしようとしていました。
Direct2D を使用して巨大なポリラインを描画してテストしたところ、GDI を使用して同じテストを実行した量の 500 分の 1 のデータでさえ、結果はとてつもなく遅くなりました (そして、GDI でバックバッファーとしてビットマップを使用することさえしませんでした。フォームキャンバスに直接描画しただけです)。
したがって、次のいずれかだと思います。a
) Direct2D は GDI より遅い。
b) TDirect2DCanvas が遅い。
c)私は何か間違ったことをしてい
ます。うまくいけば、それは 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 ポイントのポリライン (少なくとも 10K) を大量に描画する必要があるためです。
更新 (2010-11-06)
Direct2D がポリラインを好まないように思われることを以前に知りました。単一の線 (2 点のポリライン) を多く使用すると、より速く描画されます。
Chris Bensenのおかげで、アンチエイリアシングを使用しているときに大きなポリラインを使用すると速度が低下することがわかりました。そこで、Chris が提案したようにアンチエイリアシングを無効にすると、50k の線を描画するためにパフォーマンスが ~6000ms から ~3500ms になりました。
アンチエイリアシングを使用している間、Direct2D はポリラインを適切に処理しないため、まだ改善される可能性があります。アンチエイリアシングを無効にすると、まったく逆になります。
Direct2D で 50k の線を描画する時間は、アンチエイリアシングなしで大きなポリラインを描画した場合、約 50 ミリ秒です。いいね、えっ!
問題は、ビットマップに描画した場合、 GDI は Direct2D よりも高速であり、それが完了した後、結果をフォームに BitBlt で戻すと、 〜35msで描画され、同じグラフィックス品質で描画されます。また、Direct2D も既にバックバッファーを使用しているようです (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
この遅さの理由を誰かが説明してくれたらうれしいです。サンプルコードは大歓迎です。