GDI +表现技巧

Dav*_*ten 2 .net performance system.drawing gdi

有没有人知道讨论GDI +性能的任何可靠(并且希望是广泛的)书籍/网站(超出明显的范围)?

例如,我最近遇到了这个优秀的实验.我最近也注意到这种Graphics.FillPath()方式比方式更快Graphics.DrawPath().我很想知道我缺少的其他重要信息.

亲善,大卫

Jas*_*ams 19

嗯.如果您需要绘制路径的轮廓,那么知道FillPath比DrawPath更快是没有收获的!

优化GDI +的最佳方法与任何其他代码完全相同:首先,不要优化它.代替:

  • 首先写它,它只是工作,然后决定它是否实际上太慢.
  • 然后检查你的"算法":
    • 简化您的绘图(减少绘图的数量),它会更快(并且在大多数情况下,减少杂乱会更好看).
    • 您是每次都在绘制整个显示器,还是使用剪辑矩形来避免绘制不需要更新的图像部分?
    • 检查你如何绘制东西.您是否为每次重绘创建和销毁资源(例如画笔和笔)?将它们缓存在成员变量中.你是否多次过度绘制相同的像素?(例如,绘制背景,然后在顶部绘制位图,然后在其上绘制一个矩形 - 也许您可以避免这些重绘).您是否使用100个多边形线段绘制曲线时,只有10个线段看起来足够好?当窗口滚动时,您是否让操作系统移动现有图像,因此您只需要重新绘制新曝光的条带,或者您是否浪费时间重绘整个窗口?
    • 您是在使用转换还是在代码中进行冗长的定位计算?
    • 检查任何循环并确保尽可能多地移动它们的代码 - 预先计算循环中使用的值等.确保循环以尽可能顺便缓存cpu-cache的方向/方式迭代数据.
    • 您在重绘期间处理的数据中是否有任何内容?也许其中一些可以预先计算或以更加渲染的最佳形式组织.例如,一个不同类型的列表是否会更快地枚举您的数据?您是否正在处理1000个数据项以找到您需要绘制的10个数据项?
    • 你能用不同的方法实现相同的外观吗?例如,您可以通过交替绘制黑色和白色的64个方块来绘制棋盘.绘制32个黑色然后32个白色方块可能会更快,因此您可以避免在各个区域之间进行状态更改.但你实际上可以使用白色背景清晰,4个黑色矩形和4个XOR矩形(8个代替64 =>更快的算法)绘制它.
  • 图像的某些部分是否经常不会改变?尝试在屏幕外位图中缓存它们,以最大限度地减少每次重绘所需的"重建"量.请记住,您仍然可以渲染屏幕外的位图,然后在它们之上叠加图形基元,这样您可能会发现比您意识到的更多"静态"图像区域.
  • 你在渲染位图图像吗?尝试将它们转换为屏幕的像素格式,并以"原生"形式缓存它们,而不是每次绘制时都使GDI +转换它们.
  • 如果您对较低质量的折衷感到满意,那么请调低质量设置以获得更快的渲染效果

完成所有这些操作后,您就可以开始寻找有关优化渲染的书籍.如果它仍然太慢,当然.运行探查器以找出渲染的哪些部分最慢.

你认为你可以获得收益的地方,尝试不同的渲染方式(例如,有可能Graphics.Clear()比用FillRectangle()填充背景要快得多,或者不同的渲染顺序(绘制所有东西)首先是一种颜色,以防状态变化花费你的时间 - 现代图形卡的批处理操作通常非常重要.绘制多个多边形的单个调用通常比进行多个单多边形调用更快,所以你可以将所有多边形积累到延迟渲染缓冲区,然后在渲染过程结束时将它们全部提交?)

之后,您可能需要使用GDI或DirectX来更接近硬件.


Tar*_*don 10

这可能不是您正在寻找的答案,但考虑根本不使用GDI +.我不得不最近重写2D-CAM应用程序的渲染堆栈,最重要的要求是快速获得良好的抗锯齿线(抗锯齿是促使我们重写现有GDI渲染器的原因).

以下是我用200个项目渲染得到的一些结果(每个项目本身就是一些线条和小的填充形状标记).这些是帧速率(在Windows 7上),所以越高越好:

200项:GDI = 51,GDI + = 20,D2D = 59,WPF = 33,GL = 59.

(D2D是Direct2D,GL是OpenGL).您已经可以看到GDI +正在落后.WPF可能在保留模式API方面受到限制,但OpenGL也是双缓冲的,看起来也很流畅.

在1000件商品中,差异更明显:

GDI = 23,GDI + = 5,D2D = 17,WPF = 2,GL = 40.

没错,WPF现在已降至2 FPS,GDI +正以5 FPS的速度爬行.所以考虑D2D,或者简单地回到OpenGL.这就是我们现在使用的和重写3个月后,我认为我们做出了正确的选择.编程模型本身比D2D看起来要干净得多.

请注意,我们正在使用的WPF渲染是高度优化的; 没有回调,没有事件,没有约束力.我们只使用最低级别的原语获取DrawingContext并在每个帧上绘制所有内容,因此不存在事件开销.

如果您有兴趣,请告诉我,我可以寄给您使用的测试套件,这样您就可以随意使用它.

(我可能避开GDI +的一个原因是它不太可能是硬件加速).