为什么我的Direct2D绘图性能如此糟糕?

时间:2012-11-28 10:48:30

标签: .net direct2d

我正在Win7上开发一个需要执行映射的Dotnet 4.0应用程序。作为地图绘制应用程序,它输出高分辨率抗锯齿多边形的垃圾负载。它目前支持两种类型的渲染输出,GDI +和Direct2D。

我担心的是因为GDI +输出比Direct2D快了大约3倍。

两个渲染器都在使用AA。我知道我可以在Direct2D中关闭它,这有点提高了吞吐量(比GDI +低了约2倍)。但这不是一个解决方案,因为我可以在GDI +中关闭AA并在那里获得更好的性能。出于此基准测试的目的,我的渲染代码是微不足道的。我希望我犯了一些可怕的错误,有人可以指出我会纠正这种情况。

_renderTarget.BeginDraw();

// Paint background.
RectF rf = new RectF(0.0f, 0.0f, renderTargetSize.Width, renderTargetSize.Height);
_renderTarget.FillRectangle(rf, _backgroundBrush);

// Draw polygons
foreach (GisTypes.Polygon polygon in _polygons)
{
    using (PathGeometry path = _factory.CreatePathGeometry())
    {
        using (GeometrySink sink = path.Open())
        {
            sink.SetFillMode(Microsoft.WindowsAPICodePack.DirectX.Direct2D1
                .FillMode.Alternate);

            Point2F[] points = Array.ConvertAll(polygon.Points,
                x => new Point2F((float)x.X, (float)x.Y));

            sink.BeginFigure(points[0], FigureBegin.Filled);

            for (int i = 1; i < points.Length; ++i)
            {
                sink.AddLine(points[i]);
            }

            sink.EndFigure(FigureEnd.Closed);
            sink.Close();
        }

        using (TransformedGeometry transformedPath = _factory.CreateTransformedGeometry(
            path, WorldToPage))
        {
            _renderTarget.FillGeometry(transformedPath, _fillBrush);
            _renderTarget.DrawGeometry(transformedPath, _borderBrush, 1.0f);
        }
    }
}

_renderTarget.EndDraw();

在这个示例代码中,我使用一个路径,每个多边形使用一个数字。原因是它更接近于GDI +实现和实际应用,而不是示例代码,它简化了所选多边形的渲染。我知道我可以使用单一路径和多个数字,我已经尝试过这种方式,它稍微快一点但不足以对一般问题产生影响。

我也使用TransformedGeometry而不是在RenderTarget上设置变换。原因是因为虽然我想要转换几何体,但我不希望轮廓被转换,因为缩放因子会导致它完全消失。

在我使用的特定样本数据中,只有几百个多边形,但每个多边形可以有几千个点,所以我不认为在渲染过程中分配多个PathGeometry和TransformedGeometry是个问题, (因为它们并不多,我已经尝试过只使用一个PathGeometry和TransformedGeometry,差别很小。)

我想知道我是否应该渲染到屏幕外的RenderTarget并将结果显示在屏幕上的RenderTarget上,但我已经阅读了MSDN关于提高Direct2D性能的文章,并且没有提到这是一个优化。

有人有任何想法吗?

2 个答案:

答案 0 :(得分:2)

我认为您的绘图例程过于频繁地创建资源,这非常耗时。几何体和接收器为device-independent resources,只要它们未被修改,您就应该创建并保留它们。这些修改通常发生在您...更改应绘制的内容时,当然,以及移动/调整窗口大小或平移/缩放内容时。您的绘图例程将只绘制已存在的资源,并且应该更快。

希望这有帮助。

答案 1 :(得分:0)

由于您询问“是否有任何想法?”,因此此Visual Studio工具可能会有所帮助::-)

Graphics Diagnostics:可让您捕获帧并详细研究Direct3D调用的顺序;如果渲染目标是Direct3D(硬件),它可能会帮助您诊断问题 。类似于RenderDoc

Visual Studio Performance and Diagnostics Hub中的

GPU Usage工具:时序,但与Graphics Diagnostics相比,粗粒度。

Concurrency Visualizer:计时,调用堆栈,GPU使用率,并且您可以从代码中添加标记/标志。

此外,您可以在Direct2D中使用不同的渲染目标(例如,与GDI兼容的硬件),并将其与纯GDI进行比较。