2012-11-28 9 views
9

Ich entwickle eine Dotnet 4.0-Anwendung auf Win7, die Mapping durchführen muss. Als Mapping-Anwendung gibt es Mistladungen von hochauflösenden Antialiasing-Polygonen aus. Es unterstützt derzeit zwei Arten von Rendering-Ausgabe, GDI + und Direct2D.Warum ist meine Direct2D Zeichnungsleistung so schrecklich?

Ich bin besorgt, weil die GDI + -Ausgabe um einen Faktor 3 schneller ist als die Direct2D.

Beide Renderer verwenden AA. Ich weiß, dass ich es in Direct2D abschalten kann, was den Durchsatz etwas verbessert (bis zu einem Faktor 2 schlechter als GDI +). Aber das ist keine Lösung, denn ich kann AA auch in GDI + ausschalten und dort noch bessere Leistung erzielen. Für diesen Benchmark ist mein Rendering-Code trivial. Ich hoffe, ich habe einen schrecklichen Fehler gemacht, dass jemand auf mich hinweisen kann, der die Situation verbessern wird.

_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(); 

In diesem Beispielcode verwende ich einen Pfad und eine Zahl pro Polygon. Der Grund dafür ist, dass es die Implementierung von GDI + genauer widerspiegelt und in der tatsächlichen Anwendung anstelle des Beispielcodes das Rendern der ausgewählten Polyons vereinfacht. Ich weiß, dass ich einen einzigen Pfad und mehrere Zahlen verwenden kann, und ich habe es auf diese Weise versucht, es ist marginal schneller, aber nicht genug, um eine Auswirkung auf das allgemeine Problem zu haben.

Ich verwende auch eine TransformedGeometry, anstatt die Transformation auf das RenderTarget zu setzen. Der Grund dafür ist, dass, obwohl ich möchte, dass die Geometrie transformiert wird, ich nicht möchte, dass der Umriss transformiert wird, weil der Skalierungsfaktor dazu führen würde, dass er vollständig verschwindet.

In den bestimmten Beispieldaten, die ich verwende, gibt es nur ein paar hundert Polygone, aber jedes Polygon kann mehrere tausend Punkte haben, also glaube ich nicht, dass die Zuweisung von mehreren PathGeometry und TransformedGeometry während des Renderings das Problem ist , (da es nicht viele von ihnen gibt, und ich habe es bereits mit nur einer PathGeometry und TransformedGeometry versucht und der Unterschied war marginal).

Ich fragte mich, ob ich nicht zu einem Offscreen RenderTarget Rendern und das Ergebnis auf dem Bildschirm RenderTarget blitzen sollte, aber ich habe den MSDN-Artikel zur Verbesserung der Direct2D-Leistung gelesen und es nicht als eine Optimierung erwähnt.

Wer hat irgendwelche Ideen?

+0

Sie sollten nur zeichnen, was in Sicht ist. Wenn Sie Geometrien filtern, die zuerst angezeigt werden und dann nur diese anzeigen, können Sie den Code nicht ermitteln. – CodeAngry

+1

Alles ist in Sicht sowohl für D2D als auch für GDI + und jede weitere Optimierung, die ich vornehmen könnte, könnte gleichermaßen auf D2D und GDI + angewendet werden, was nicht erklären würde, warum die D2D-Leistung im Vergleich zu GDI + so schlecht ist. – Neutrino

+0

Ich bin am selben Punkt (Ich füge Unterstützung für das Rendern mit Direct2D hinzu) und ich glaube, dass Offscreen-Rendering helfen sollte (ich denke, dass es in diesem Thema nicht erwähnt wird, weil sie dynamische Szene statt statisch annehmen). Ist es Ihnen gelungen, dieses Problem irgendwie zu lösen? – Victoria

Antwort

2

Ich glaube, dass Ihre Zeichenroutine Ressourcen zu oft erstellt, was wirklich zeitaufwendig ist. Geometrien und Sinks sind device-independent resources. Sie sollten sie erstellen und beibehalten, solange sie nicht geändert werden. Diese Änderungen treten normalerweise auf, wenn Sie ... das ändern, was gezeichnet werden soll, und natürlich, wenn Sie das Fenster verschieben/skalieren oder den Inhalt verschieben/zoomen. Ihre Zeichenroutine würde dann nur bereits vorhandene Ressourcen zeichnen und sollte schneller sein.

Hoffe, das hilft.

+0

Danke dafür, aber was du vorschlägst ist was ich schon mache.Die oben genannte Routine wird in der WPF-Entsprechung von WM_PAINT aufgerufen und wird daher nur ausgeführt, wenn die Ansicht geschwenkt oder gezoomt wird, und die gerenderten Daten sind nur diejenigen, die sich innerhalb des sichtbaren Bereichs befinden. Während es stimmt, dass ich weniger zeichnen würde, würde es schneller rendern, aber genauso, wenn ich weniger mit GDI zeichne, die auch noch schneller rendern wird, erklärt weniger Rendering zur Verbesserung der D2D Leistung nicht die schlechte Leistung von D2D relativ zu GDI. – Neutrino

+0

Ok, ich wusste nicht, dass du WPF benutzt hast. Ich nehme an, dass du deine Routine bereits so profiliert hast, dass du weißt, welche Anweisungen so viel Zeit brauchen, also habe ich keine andere Idee, sorry. – Papaya

Verwandte Themen