【发布时间】:2011-05-02 14:40:33
【问题描述】:
在寻找替代 GDI 的替代品时,我试图在 Windows 7 中测试 Delphi 的 2010 TDirect2DCanvas 性能。
我通过使用 Direct2D 绘制一条巨大的折线对其进行了测试,结果速度非常慢,即使数据量比我使用 GDI 运行相同测试的数据量少 500 倍(我什至没有使用位图作为后缓冲在 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 返回到表单,它会以大约 35 毫秒的速度绘制 >,并具有相同的图形质量。而且,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
如果有人能解释我为什么会这样慢,我会很高兴。非常感谢示例代码。
【问题讨论】:
-
尝试使用性能分析器。也许幕后正在进行一项不明显的昂贵操作。
-
我没有任何答案,但我知道你不是第一个提到它似乎并不比 GDI 快的人。
标签: delphi delphi-2010 gdi delphi-xe direct2d