使用sharpdx绘制巨大图形时的性能问题

时间:2016-01-05 11:47:31

标签: c# graph directx sharpdx

我的任务是绘制一个包含超过500,000个节点和边的巨大图形,具有移动节点,选择它们,移除等功能。 我正在使用C#.Net 4.6 winform applicatoin 我正在使用sharpdx(.net的directx包装器),但我有性能问题,每个渲染循环需要750ms~1.3 fps,这是不可接受的!我的GPU负载也不到10%,所以看起来我并没有完全使用我的GPU。我正在使用Direct2D,我为每个节点和边缘调用Draw方法(我认为这是主要问题!)。
我的问题是如何以合理的性能完成这项任务? 或者我如何减少平局调用。像批量抽奖这样的东西?

这是我的代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.Windows;
namespace SharpD2D
{
    public partial class Form1 : Form
    {
        List<Geometry> lstGeoms;
        public Factory Factory2D { get; private set; }
        public SharpDX.DirectWrite.Factory FactoryDWrite { get; private set; }
        public RenderTarget RenderTarget2D { get; private set; }
        public RenderControl renderControl { get; private set; }
    public Form1()
    {
        InitializeComponent();
        InitRendererControl(this.Size);
        InitDirect2DAndDirectWrite();
        lstGeoms = Generator.GeomGenerator.getGeoms(Factory2D);
    }

    private void InitRendererControl(System.Drawing.Size? renderSize = null)
    {
        // create instance
        renderControl = new RenderControl();
        //  renderControl.BackColor = System.Drawing.Color.Transparent;

        if (renderSize.HasValue)
            renderControl.Size = renderControl.ClientSize = renderSize.Value;

        //events
        renderControl.Paint += renderControl_Paint;

        this.Controls.Add(renderControl);
    }

    private void renderControl_Paint(object sender, PaintEventArgs e)
    {
        renderBoard();

    }

    private void InitDirect2DAndDirectWrite()
    {
        Factory2D = new SharpDX.Direct2D1.Factory(FactoryType.MultiThreaded);
        FactoryDWrite = new SharpDX.DirectWrite.Factory(SharpDX.DirectWrite.FactoryType.Shared);


        var properties = new HwndRenderTargetProperties();
        properties.Hwnd = renderControl.Handle;

        properties.PixelSize = new Size2(renderControl.ClientSize.Width, renderControl.ClientSize.Height);
        properties.PresentOptions = PresentOptions.RetainContents;

        RenderTarget2D = new WindowRenderTarget(Factory2D, new RenderTargetProperties(new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.Unknown, AlphaMode.Premultiplied)), properties);
        RenderTarget2D.AntialiasMode = AntialiasMode.Aliased;
        RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Aliased;
    }

    private void renderBoard()
    {
        RenderTarget2D.AntialiasMode = AntialiasMode.Aliased;
        Stopwatch sw = new Stopwatch();
        var brush = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget2D, new Color4(0.3f, 0.5f, 0.9f, 1f));

        RenderLoop.Run(renderControl, () =>
        {
            sw.Restart();

            RenderTarget2D.BeginDraw();
            RenderTarget2D.Clear(new Color4(0f, 0f, 0f, 1f));
            foreach (var item in lstGeoms)
            {
                RenderTarget2D.FillGeometry(item, brush);
            }
            RenderTarget2D.Flush();
            RenderTarget2D.EndDraw();
            sw.Stop();
            var totalElappsed = sw.ElapsedMilliseconds;
            var fps = 1000 / (totalElappsed == 0 ? 0.000001 : totalElappsed);
            Console.WriteLine($"Count: {lstGeoms.Count} : {totalElappsed.ToString()} , {fps}");

        });
    }
}
}

GeomGenerator类产生500k随机椭圆:

using SharpDX;
using SharpDX.Direct2D1;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Generator
{
    public class GeomGenerator
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct Vertex
        {
            public Vector4 Position;
            public SharpDX.ColorBGRA Color;
        }
        public static List<Geometry> getGeoms(SharpDX.Direct2D1.Factory d2dFactory)
        {
            var lstGeoms = new List<Geometry>();
            int count = 500 * 1000;
            Random r = new Random();
            var bound = 650;
            var lowerBound = 0;
            var upperBound = bound;

            for (int i = 0; i < count; i++)
            {
                var location = new Point(r.Next(lowerBound, upperBound), r.Next(lowerBound, upperBound));
                var center = new SharpDX.Mathematics.Interop.RawVector2() { X = location.X, Y = location.Y };
                var ellipse = new SharpDX.Direct2D1.Ellipse(center, 1, 1);
                var mainGeo = new EllipseGeometry(d2dFactory, ellipse);
                lstGeoms.Add(mainGeo);

            }
            return lstGeoms;
        }

    }
}

提前致谢。

0 个答案:

没有答案