11

我正在 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,但我已经阅读了有关提高 Direct2D 性能的 MSDN 文章,它没有提到这是一种优化。

有人有什么想法吗?

4

2 回答 2

3

我相信你的绘图程序太频繁地创建资源,这真的很耗时。Geometries 和 Sinks 是与设备无关的资源,您应该创建并保留它们,只要它们不被修改。这些修改通常发生在您...更改应该绘制的内容时,以及当您移动/调整窗口大小或平移/缩放内容时。然后,您的绘图例程将仅绘制现有资源,并且应该更快。

希望这可以帮助。

于 2013-01-07T07:28:25.823 回答
0

既然您问“有什么想法吗?”,这个 Visual Studio 工具可能会有所帮助::-)

图形诊断:让您捕获帧并以极其详细的方式探索 Direct3D 调用的顺序;如果您的渲染目标是 Direct3D(硬件),它可能会帮助您诊断问题。类似于RenderDoc

Visual Studio 性能和诊断中心中的GPU 使用工具:计时,但与图形诊断相比粒度比较粗。

并发可视化工具:计时、调用堆栈、GPU 使用情况,您可以从代码中添加标记/标志。

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

于 2018-07-17T16:36:02.133 回答