【问题标题】:Direct2D plot approach / performanceDirect2D 绘图方法/性能
【发布时间】:2015-02-16 08:26:02
【问题描述】:

使用 Direct2D (Sharpdx) 绘制复杂绘图的方法如何?

实际上我使用的是 WindowsRenderTarget,将它与 Direct2D1.Factory 连接并绘制到 RenderControl。

        Factory2D = new SharpDX.Direct2D1.Factory(FactoryType.MultiThreaded);
        FactoryWrite = new SharpDX.DirectWrite.Factory();
        var properties = new HwndRenderTargetProperties();
        properties.Hwnd = this.Handle;
        properties.PixelSize = new Size2(this.ClientSize.Width, this.ClientSize.Height);
        properties.PresentOptions = PresentOptions.RetainContents;

        RenderTarget2D = new WindowRenderTarget(Factory2D, new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)), properties);
        RenderTarget2D.AntialiasMode = AntialiasMode.PerPrimitive;

绘图是在窗体的 Paint Event 中完成的:

RenderTarget2D.BeginDraw();
RenderTarget2D.Clear(Color4.Black);
drawProgress(); // Doing Paintings like DrawLine, Multiple PathGeometrys, DrawEllipse and DrawText
RenderTarget2d.EndDraw();

在 MouseMove/MouseWheel 事件中,将重新计算绘图(用于缩放或计算将要显示的元素)。这个过程大约需要8-10ms。 下一步其实是

this.Refresh(); 

这里,我猜,是问题所在,这个进度需要长达 140ms。

所以情节的缩放/移动大约有 7fps。

另外程序在刷新控件时占用的内存越来越大

////编辑

线条画法:

    private void drawLines(Pen pen, PointF[] drawElements)
    {
        SolidColorBrush tempBrush = new SolidColorBrush(RenderTarget2D, SharpDX.Color.FromRgba(pen.Color.ToArgb()));

        int countDrawing = (drawElements.Length / 2) + drawElements.Length % 2;

        for (int i = 0; i < countDrawing; i++)
        {
            drawLine(new Vector2(drawElements[i].X, drawElements[i].Y), new Vector2(drawElements[i + 1].X, drawElements[i + 1].Y), brushWhite);
        }
    }

绘制几何图形:

RenderTarget2D.DrawGeometry(graphicPathToPathGeometry(p), penToSolidColorBrush(pen));

    private PathGeometry graphicPathToPathGeometry(GraphicsPath path)
    {
        geometry = new PathGeometry(Factory2D);
        sink = geometry.Open();
        if (path.PointCount > 0)
        {
            sink.BeginFigure(new Vector2(path.PathPoints[path.PointCount - 1].X, path.PathPoints[path.PointCount - 1].Y), FigureBegin.Hollow);
            sink.AddLines(pointFToVector2(path.PathPoints));
            sink.EndFigure(new FigureEnd());
            sink.Close();
        }
        return geometry;
    }

在鼠标移动中,仅通过建立 Cursor.Position.X/Y old 和 Cursor.Position.X/Y new 之间的差异来重新计算绘图。所以这些线会经常重新计算:)

【问题讨论】:

  • 据我了解,您在 MouseMove/MouseWheel 结束时调用this.Refresh(),对吗?您如何准确地衡量性能?当您从第一个 sn-p 初始化资源时?您的第二个 sn-p 是 Paint 事件的全部内容吗?您是否在 drawProgress() 中创建任何资源?
  • 我用秒表测量它,该秒表将在刷新事件中重置。实际上我开始使用渲染循环并在那里做油漆。我想问题是绘图过程。我实际上每次都重新绘制完整的画,即使屏幕是空白的。我认为我的方法是错误的。另一件事是内存使用情况。程序越来越大。我从不处理任何东西,但也不知道该怎么做。渲染目标被渲染循环阻塞
  • 没有看到你的绘图过程(即-drawProgress()),我们只会猜测。
  • 绘制进度有大量计算 :) 大约 500 条绘制线,300 条路径几何(没有复杂的,但这是最大的性能不足),100 条椭圆。但这不是问题。问题是我每帧都重新绘制这些东西。我使用了 MiniRect 示例作为基础。也没有重置 RenderTarget 来清除内存。我认为我使用了错误的基础知识,我从不使用 SwapChain 或 Backbuffer。我从来没有设置视口或类似的东西。当我的程序运行 30 秒时,它达到 1,6gigs ram:/
  • 我只能猜测...您可能正在drawProgress() 中创建资源。你不应该。一个核心原则是您必须立即创建资源,然后在您的绘图例程中重用它们。 “重置 RenderTarget”是什么意思?另外,您有独立的视频适配器还是使用 cpu 集成的适配器?

标签: c# performance direct2d sharpdx


【解决方案1】:

主要瓶颈是您的graphicPathToPathGeometry() 函数。您正在渲染循环中创建和“填充”PathGeometry。正如我上面提到的,一个核心原则是您必须立即创建资源,然后在您的绘图例程中重用它们。

关于您的内存泄漏...您的代码示例没有提供足够的信息,但很可能您没有释放您正在创建的资源(即PathGeometrySolidColorBrush 以及我们看不到的资源)。

最简单的建议是 - 仅将渲染循环用于渲染/绘图和重用资源,而不是重新创建它们。

Improving the performance of Direct2D apps

【讨论】:

  • 你是绝对正确的。对我来说,作为一个初学者,在渲染循环中计算一些东西并不是那么清楚
【解决方案2】:

问题的一部分是:

SolidColorBrush tempBrush = new SolidColorBrush(RenderTarget2D, SharpDX.Color.FromRgba(pen.Color.ToArgb()));

在渲染循环中创建任何类型的对象都会导致应用程序内存不足。绘制现有值是要走的路。

我猜性能问题也会基于这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-16
    • 2020-02-28
    • 2016-06-11
    • 2021-12-03
    • 1970-01-01
    • 2013-11-01
    • 1970-01-01
    • 2020-02-24
    相关资源
    最近更新 更多