Freigeben über


Verbessern der Leistung von Direct2D-Apps

Obwohl Direct2D hardwarebeschleunigt ist und für hohe Leistung vorgesehen ist, müssen Sie die Features korrekt verwenden, um den Durchsatz zu maximieren. Die hier gezeigten Techniken werden von der Untersuchung allgemeiner Szenarien abgeleitet und gelten möglicherweise nicht für alle App-Szenarien. Daher können ein sorgfältiges Verständnis des App-Verhaltens und der Leistungsziele dazu beitragen, die gewünschten Ergebnisse zu erzielen.

Ressourcennutzung

Eine Ressource ist eine Zuordnung bestimmter Art, entweder im Video- oder Systemspeicher. Bitmaps und Pinsel sind Beispiele für Ressourcen.

In Direct2D können Ressourcen sowohl in Software als auch in Hardware erstellt werden. Ressourcenerstellung und -löschung auf Hardware sind kostspielige Vorgänge, da sie viel Aufwand für die Kommunikation mit der Grafikkarte erfordern. Lassen Sie uns betrachten, wie Direct2D Inhalte in ein Zielobjekt rendert.

In Direct2D werden alle Renderingbefehle zwischen einem Aufruf von BeginDraw und einem Aufruf von EndDraw eingeschlossen. Diese Aufrufe werden an ein Rendering-Ziel gesendet. Sie müssen die BeginDraw-Methode aufrufen, bevor Sie Renderingvorgänge aufrufen. Nachdem Sie BeginDraw aufgerufen haben, erstellt ein Kontext in der Regel einen Batch von Renderingbefehlen, verzögert jedoch die Verarbeitung dieser Befehle, bis eine dieser Anweisungen zutrifft:

  • EndDraw aufgetreten. Wenn EndDraw aufgerufen wird, werden alle Batchzeichnungsvorgänge abgeschlossen und der Status des Vorgangs zurückgegeben.
  • Sie rufen "Flush" explizit auf: Die Flush-Methode bewirkt, dass der Batch verarbeitet wird und alle ausstehenden Befehle ausgegeben werden.
  • Der Puffer, der die Renderingbefehle hält, ist voll. Wenn dieser Puffer voll wird, bevor die beiden vorherigen Bedingungen erfüllt sind, werden die Renderingbefehle geleert.

Bis die Primitive geleert werden, behält Direct2D interne Verweise auf entsprechende Ressourcen wie Bitmaps und Pinsel.

Ressourcen wiederverwenden

Wie bereits erwähnt, ist die Ressourcenerstellung und -löschung auf Hardware teuer. Verwenden Sie also Ressourcen nach Möglichkeit wieder. Nehmen Sie das Beispiel der Erstellung von Bitmaps in der Spieleentwicklung. In der Regel werden Bitmaps, die eine Szene in einem Spiel bilden, gleichzeitig mit allen unterschiedlichen Variationen erstellt, die für das spätere Rendern von Frame-zu-Frame erforderlich sind. Zum Zeitpunkt des tatsächlichen Szenenrenderings und des erneuten Renderns werden diese Bitmaps nicht erneut erstellt, sondern wiederverwendet.

Hinweis

Sie können Ressourcen für die Fenstergrößenänderung nicht wiederverwenden. Wenn die Größe eines Fensters geändert wird, müssen einige skalierungsabhängige Ressourcen wie kompatible Renderziele und möglicherweise einige Layerressourcen neu erstellt werden, da der Fensterinhalt neu gezeichnet werden muss. Dies kann wichtig sein, um die Gesamtqualität der gerenderten Szene aufrechtzuerhalten.

 

Beschränken der Verwendung von Flush

Da die Flush-Methode bewirkt, dass die Batchrenderingbefehle verarbeitet werden, empfehlen wir, sie nicht zu verwenden. Verlassen Sie für die meisten gängigen Szenarien die Ressourcenverwaltung auf Direct2D.

Bitmaps

Wie bereits erwähnt, sind Ressourcenerstellung und -löschung sehr kostspielige Vorgänge in der Hardware. Eine Bitmap ist eine Art ressource, die häufig verwendet wird. Das Erstellen von Bitmaps auf der Grafikkarte ist teuer. Wenn Sie sie wiederverwenden, kann die Anwendung schneller werden.

Große Bitmaps erstellen

Grafikkarten weisen in der Regel eine minimale Speicherzuweisungsgröße auf. Wenn eine Zuordnung angefordert wird, die kleiner als diese ist, wird eine Ressource dieser Mindestgröße zugeordnet, und der überschüssige Speicher wird verschwendet und für andere Dinge nicht verfügbar. Wenn Sie viele kleine Bitmaps benötigen, empfiehlt es sich, eine große Bitmap zuzuweisen und alle kleinen Bitmapinhalte in dieser großen Bitmap zu speichern. Dann können Unterbereiche der größeren Bitmap gelesen werden, wo die kleineren Bitmaps benötigt werden. Häufig sollten Sie Zwischenabstand (transparente schwarze Pixel) zwischen den kleinen Bitmaps einfügen, um eine Interaktion zwischen den kleineren Bildern während des Betriebs zu vermeiden. Dies wird auch als Atlas bezeichnet, und es hat den Vorteil, den Aufwand für die Bitmaperstellung und die Speicherverschwendung kleiner Bitmap-Zuordnungen zu reduzieren. Es wird empfohlen, die meisten Bitmaps auf mindestens 64 KB zu beschränken und die Anzahl der Bitmaps einzuschränken, die kleiner als 4 KB sind.

Erstellen eines Atlass von Bitmaps

Es gibt einige häufige Szenarien, für die ein Bitmapatlas sehr gut dienen kann. Kleine Bitmaps können in einer großen Bitmap gespeichert werden. Diese kleinen Bitmaps können bei Bedarf aus der größeren Bitmap gezogen werden, indem Sie das Zielrechteck angeben. Beispielsweise muss eine Anwendung mehrere Symbole zeichnen. Alle mit den Symbolen verbundenen Bitmaps können im Voraus in eine große Bitmap geladen werden. Und zum Rendern können sie aus der großen Bitmap abgerufen werden.

Hinweis

Eine im Videospeicher erstellte Direct2D-Bitmap ist auf die maximale Bitmapgröße beschränkt, die vom Adapter unterstützt wird, auf dem sie gespeichert ist. Das Erstellen einer Bitmap, die größer ist als dies zu einem Fehler führen kann.

 

Hinweis

Ab Windows 8 enthält Direct2D einen Atlas-Effekt , der diesen Prozess vereinfachen kann.

 

Gemeinsame Bitmaps erstellen

Durch das Erstellen freigegebener Bitmaps können erweiterte Aufrufer Direct2D-Bitmapobjekte erstellen, die direkt von einem vorhandenen Objekt unterstützt werden, das bereits mit dem Renderziel kompatibel ist. Dies vermeidet das Erstellen mehrerer Oberflächen und trägt dazu bei, den Leistungsaufwand zu reduzieren.

Hinweis

Gemeinsam genutzte Bitmaps sind in der Regel auf Softwareziele oder auf kompatible Ziele mit DXGI beschränkt. Verwenden Sie die Methoden CreateBitmapFromDxgiSurface, CreateBitmapFromWicBitmap und CreateSharedBitmap , um freigegebene Bitmaps zu erstellen.

 

Kopieren von Bitmaps

Das Erstellen einer DXGI-Oberfläche ist ein kostspieliger Vorgang, sodass vorhandene Oberflächen bei Bedarf wiederverwendet werden. Selbst bei Software, wenn eine Bitmap hauptsächlich in der gewünschten Form vorliegt, mit Ausnahme eines kleinen Teils, ist es besser, diesen Teil zu aktualisieren, anstatt die gesamte Bitmap zu verwerfen und alles neu zu erstellen. Obwohl Sie CreateCompatibleRenderTarget verwenden können, um dieselben Ergebnisse zu erzielen, ist das Rendern im Allgemeinen ein wesentlich teurerer Vorgang als das Kopieren. Dies liegt daran, dass die Hardware, um die Cachelokalität zu verbessern, keine Bitmap in derselben Speicherreihenfolge speichert, die die Bitmap adressiert. Stattdessen könnte die Bitmap durcheinander gewürfelt werden. Das Swizzling wird vor der CPU versteckt, entweder durch den Treiber (der langsam ist und nur auf den billigeren Teilen verwendet wird) oder durch den Speichermanager auf der GPU. Aufgrund der Einschränkungen, wie Daten beim Rendern in ein Rendering-Ziel geschrieben werden, werden Rendering-Ziele in der Regel entweder gar nicht oder auf eine weniger optimale Art und Weise gerendert, als dies möglich wäre, wenn Sie wissen, dass Sie nie auf die Oberfläche rendern müssen. Daher werden die CopyFrom*-Methoden zum Kopieren von Rechtecke aus einer Quelle in die Direct2D-Bitmap bereitgestellt.

CopyFrom kann in jeder seiner drei Formen verwendet werden:

Gekachelte Bitmap über Dashing verwenden

Das Rendern einer gestrichelten Linie ist aufgrund der hohen Qualität und Genauigkeit des zugrunde liegenden Algorithmus eine sehr teure Operation. Für die meisten Fälle, in denen keine retilinearen Geometrien beteiligt sind, kann der gleiche Effekt mithilfe von nebeneinander angeordneten Bitmaps schneller generiert werden.

Allgemeine Richtlinien für das Rendern komplexer statischer Inhalte

Speichern Sie Inhalte im Cache, wenn Sie denselben Inhaltsframe mehrmals hintereinander rendern, insbesondere wenn die Szene komplex ist.

Es gibt drei Zwischenspeicherungstechniken, die Sie verwenden können:

  • Vollständiges Zwischenspeichern von Szenen mithilfe einer Farbbitmap.
  • Zwischenspeicherung pro Primitiv mit einer A8-Bitmap und der Methode FillOpacityMask .
  • Per-primitive Zwischenspeicherung unter Verwendung von Geometrie-Realisierungen.

Sehen wir uns jedes dieser Details genauer an.

Vollständiges Zwischenspeichern von Szenen mithilfe einer Farbbitmap

Wenn Sie statische Inhalte rendern, erstellen Sie in Szenarien wie Animation eine weitere vollfarbige Bitmap, anstatt direkt in die Bildschirmbitmap zu schreiben. Speichern Sie das aktuelle Ziel, legen Sie das Ziel auf die Zwischenbitmap fest, und rendern Sie den statischen Inhalt. Wechseln Sie dann zurück zur ursprünglichen Bildschirmbitmap, und zeichnen Sie die Zwischenbitmap darauf.

Ein Beispiel:

// Create a bitmap.
m_d2dContext->CreateBitmap(size, nullptr, 0,
    D2D1::BitmapProperties(
        D2D1_BITMAP_OPTIONS_TARGET,
        D2D1::PixelFormat(
            DXGI_FORMAT_B8G8R8A8_UNORM,
            D2D1_ALPHA_MODE_PREMULTIPLIED),
        dpiX, dpiY),
    &sceneBitmap);

// Preserve the pre-existing target.
ComPtr<ID2D1Image> oldTarget;
m_d2dContext->GetTarget(&oldTarget);

// Render static content to the sceneBitmap.
m_d2dContext->SetTarget(sceneBitmap.Get());
m_d2dContext->BeginDraw();
…
m_d2dContext->EndDraw();

// Render sceneBitmap to oldTarget.
m_d2dContext->SetTarget(oldTarget.Get());
m_d2dContext->DrawBitmap(sceneBitmap.Get());

Dieses Beispiel verwendet Zwischen-Bitmaps für die Zwischenspeicherung und wechselt die Bitmap, auf die der Gerätekontext beim Rendern zeigt. Dies vermeidet die Notwendigkeit, ein kompatibles Renderziel für denselben Zweck zu erstellen.

Zwischenspeicherung pro Primitiv mit einer A8-Bitmap und der Methode FillOpacityMask

Wenn die vollständige Szene nicht statisch ist, sondern aus Elementen wie Geometrie oder Text besteht, die statisch sind, können Sie eine einfache Zwischenspeicherungsmethode verwenden. Diese Technik bewahrt die Antialiasingeigenschaften des Primitivs, das zwischengespeichert wird, und funktioniert mit verschiedenen Pinseltypen. Es verwendet eine A8-Bitmap, bei der A8 eine Art Pixelformat ist, das einen Alphakanal mit 8 Bit darstellt. A8 Bitmaps sind nützlich für das Zeichnen von Geometrie/Text als Maske. Wenn Sie die Deckkraft statischer Inhalte bearbeiten müssen, anstatt den Inhalt selbst zu bearbeiten, können Sie die Deckkraft der Maske übersetzen, drehen, schiefen oder skalieren.

Ein Beispiel:

// Create an opacity bitmap.
m_d2dContext->CreateBitmap(size, nullptr, 0,
    D2D1::BitmapProperties(
        D2D1_BITMAP_OPTIONS_TARGET,
        D2D1::PixelFormat(
            DXGI_FORMAT_A8_UNORM,
            D2D1_ALPHA_MODE_PREMULTIPLIED),
        dpiX, dpiY),
    &opacityBitmap);

// Preserve the pre-existing target.
ComPtr<ID2D1Image> oldTarget;
m_d2dContext->GetTarget(&oldTarget);

// Render to the opacityBitmap.
m_d2dContext->SetTarget(opacityBitmap.Get());
m_d2dContext->BeginDraw();
…
m_d2dContext->EndDraw();

// Call the FillOpacityMask method
// Note: for this call to work correctly the anti alias mode must be D2D1_ANTIALIAS_MODE_ALIASED. 
m_d2dContext->SetTarget(oldTarget.Get());
m_d2dContext->FillOpacityMask(
    opacityBitmap.Get(),
    m_contentBrush().Get(),
    D2D1_OPACITY_MASK_CONTENT_GRAPHICS);

Per-primitive Zwischenspeicherung unter Verwendung von Geometrie-Realisierungen

Eine weitere primitive Zwischenspeicherungstechnik, die so genannte Geometrie-Realisierung, bietet mehr Flexibilität beim Umgang mit Geometrie. Wenn Sie wiederholt Aliasing- oder Anti-Aliasing-Geometrien zeichnen möchten, ist es schneller, diese in Geometrie-Realisierungen zu konvertieren und die Realisierungen wiederholt zu zeichnen, als die Geometrien selbst. Außerdem verbrauchen Geometriedarstellungen in der Regel weniger Speicherplatz als Deckkraftmasken (insbesondere bei großen Geometrien) und sie reagieren weniger empfindlich auf Maßstabsänderungen. Weitere Informationen finden Sie unter Geometry Realizations Overview.

Ein Beispiel:

    // Compute a flattening tolerance based on the scales at which the realization will be used.
    float flatteningTolerance = D2D1::ComputeFlatteningTolerance(...);

    ComPtr<ID2D1GeometryRealization> geometryRealization;

    // Create realization of the filled interior of the geometry.
    m_d2dDeviceContext1->CreateFilledGeometryRealization(
        geometry.Get(),
        flatteningTolerance,
        &geometryRealization
        );

    // In your app's rendering code, draw the geometry realization with a brush.
    m_d2dDeviceContext1->BeginDraw();
    m_d2dDeviceContext1->DrawGeometryRealization(
        geometryRealization.Get(),
        m_brush.Get()
        );
    m_d2dDeviceContext1->EndDraw();

Rendering der Geometrie

Bestimmte Zeichenprimitive über Zeichengeometrie verwenden

Verwenden Sie spezifischereDraw-Primitive-Aufrufe wie DrawRectangle über generische DrawGeometry-Aufrufe . Dies liegt daran, dass bei DrawRectangle die Geometrie bereits bekannt ist, sodass das Rendern schneller ist.

Rendern statischer Geometrie

In Szenarien, in denen die Geometrie statisch ist, verwenden Sie die oben erläuterten Techniken für das Zwischenspeichern von Primitiven. Deckkraftmasken und Geometriedarstellungen können die Rendering-Geschwindigkeit von Szenen, die statische Geometrie enthalten, erheblich verbessern.

Verwenden Sie einen Multithreading-Gerätekontext

Anwendungen, die erwarten, dass große Mengen komplexer geometrischer Inhalte gerendert werden, sollten beim Erstellen eines Direct2D-Gerätekontexts das D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTI_THREADED_OPTIMIZATIONS Flag angeben. Wenn dieses Flag angegeben wird, verteilt Direct2D das Rendering über alle logischen Kerne, die auf dem System vorhanden sind, wodurch die Gesamtrenderingzeit erheblich verringert werden kann.

Hinweise:

  • Ab Windows 8.1 wirkt sich dieses Flag nur auf die Darstellung von Pfadgeometrien aus. Sie hat keine Auswirkungen auf Szenen, die nur andere Grundtypen enthalten (z. B. Text, Bitmaps oder Geometrie-Realisierungen).
  • Dieses Kennzeichen hat auch keine Auswirkungen beim Rendern in Software (d. h. beim Rendern mit einem WARP Direct3D-Gerät). Um das Software-Multithreading zu steuern, sollten Aufrufer bei der Erstellung des WARP Direct3D-Geräts das Flag D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS verwenden.
  • Die Angabe dieses Flags kann den Spitzenwert der Arbeitsmenge während des Renderings erhöhen und auch den Thread-Konflikt in Anwendungen, die bereits die Vorteile der Multithreading-Verarbeitung nutzen, verstärken.

Zeichnen von Text mit Direct2D

Die Direct2D-Textrenderingfunktion wird in zwei Teilen angeboten. Der erste Teil, der als ID2D1RenderTarget::DrawText- und ID2D1RenderTarget::DrawTextLayout-Methode verfügbar gemacht wird, ermöglicht es einem Aufrufer, entweder eine Zeichenfolge und Formatierungsparameter oder ein DWrite-Textlayoutobjekt für mehrere Formate zu übergeben. Dies sollte für die meisten Anrufer geeignet sein. Die zweite Möglichkeit zum Rendern von Text, die als ID2D1RenderTarget::D rawGlyphRun-Methode verfügbar gemacht wird, bietet Rasterung für Kunden, die bereits die Position der Glyphen kennen, die sie rendern möchten. Die folgenden beiden allgemeinen Regeln können die Textleistung beim Zeichnen in Direct2D verbessern.

DrawTextLayout vs. DrawText

Sowohl DrawText als auch DrawTextLayout ermöglichen einer Anwendung das einfache Rendern von Text, der von der DirectWrite-API formatiert ist. DrawTextLayout zeichnet ein vorhandenes DWriteTextLayout -Objekt in renderTarget, und DrawText erstellt ein DirectWrite-Layout für den Aufrufer basierend auf den Parametern, die übergeben werden. Wenn derselbe Text mehrmals gerendert werden muss, verwenden Sie DrawTextLayout anstelle von DrawText, da DrawText jedes Mal ein Layout erstellt, wenn er aufgerufen wird.

Auswählen des richtigen Textrenderingmodus

Legen Sie den Text-Antialias-Modus explizit auf D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE fest. Die Qualität des Renderns von Graustufentext ist mit ClearType vergleichbar, ist aber viel schneller.

Zwischenspeicherung

Verwenden Sie das Zwischenspeichern von Bitmaps für die gesamte Szene oder für jedes Primitiv wie beim Zeichnen anderer Primitive.

Ausschneiden einer beliebigen Form

Die folgende Abbildung zeigt das Ergebnis des Anwendens eines Clips auf ein Bild.

Ein Bild, das ein Beispiel für ein Bild vor und nach einem Clip zeigt.

Sie können dieses Ergebnis erzielen, indem Sie Ebenen mit einer Geometriemaske oder die Methode FillGeometry mit einem Deckkraftpinsel verwenden.

Hier ist ein Beispiel, das eine Ebene verwendet:

// Call PushLayer() and pass in the clipping geometry.
m_d2dContext->PushLayer(
    D2D1::LayerParameters(
        boundsRect,
        geometricMask));

Hier ist ein Beispiel, das die FillGeometry-Methode verwendet:

// Create an opacity bitmap and render content.
m_d2dContext->CreateBitmap(size, nullptr, 0,
    D2D1::BitmapProperties(
        D2D1_BITMAP_OPTIONS_TARGET,
        D2D1::PixelFormat(
            DXGI_FORMAT_A8_UNORM,
            D2D1_ALPHA_MODE_PREMULTIPLIED),
        dpiX, dpiY),
    &opacityBitmap);

m_d2dContext->SetTarget(opacityBitmap.Get());
m_d2dContext->BeginDraw();
…
m_d2dContext->EndDraw();

// Create an opacity brush from the opacity bitmap.
m_d2dContext->CreateBitmapBrush(opacityBitmap.Get(),
    D2D1::BitmapBrushProperties(),
    D2D1::BrushProperties(),
    &bitmapBrush);

// Call the FillGeometry method and pass in the clip geometry and the opacity brush
m_d2dContext->FillGeometry( 
    clipGeometry.Get(),
    brush.Get(),
    opacityBrush.Get()); 

Wenn Sie in diesem Codebeispiel die PushLayer-Methode aufrufen, übergeben Sie keine von der App erstellte Ebene. Direct2D erstellt eine Ebene für Sie. Direct2D kann die Zuordnung und Zerstörung dieser Ressource ohne Beteiligung der App verwalten. Dadurch kann Direct2D Ebenen intern wiederverwenden und Ressourcenverwaltungsoptimierungen anwenden.

In Windows 8 wurden viele Optimierungen an der Verwendung von Layern vorgenommen, und wir empfehlen, layer-APIs anstelle von FillGeometry nach Möglichkeit zu verwenden.

PushLayer in Windows 8

Die ID2D1DeviceContext-Schnittstelle wird von der ID2D1RenderTarget-Schnittstelle abgeleitet und ist der Schlüssel zum Anzeigen von Direct2D-Inhalten in Windows 8. Weitere Informationen zu dieser Schnittstelle finden Sie unter "Geräte- und Gerätekontexte". Mit der Gerätekontextschnittstelle können Sie den Aufruf der CreateLayer-Methode überspringen und dann NULL an die ID2D1DeviceContext::P ushLayer-Methode übergeben. Direct2D verwaltet automatisch die Layerressource und kann Ressourcen zwischen Ebenen und Effektdiagrammen gemeinsam nutzen.

Achsial ausgerichtete Clips

Wenn der zu beschneidende Bereich nicht beliebig, sondern an der Achse der Zeichenfläche ausgerichtet ist. Dieser Fall eignet sich für die Verwendung eines Clip-Rechtecks anstelle einer Ebene. Der Leistungsgewinn ist bei aliasierter Geometrie größer als bei antialiasierter Geometrie. Weitere Informationen zu achsenausgerichteten Clips finden Sie im Thema PushAxisAlignedClip .

DXGI-Interoperabilität: Vermeiden häufiger Switches

Direct2D kann nahtlos mit Direct3D-Oberflächen zusammenarbeiten. Dies ist sehr hilfreich beim Erstellen von Anwendungen, die eine Mischung aus 2D- und 3D-Inhalten rendern. Jeder Wechsel zwischen dem Zeichnen von Direct2D- und Direct3D-Inhalten wirkt sich jedoch auf die Leistung aus.

Beim Rendern auf einer DXGI-Oberfläche speichert Direct2D den Zustand der Direct3D-Geräte beim Rendern und Wiederherstellen, wenn das Rendern abgeschlossen ist. Jedes Mal, wenn ein Batch von Direct2D-Rendering abgeschlossen ist, werden die Kosten für dieses Speichern und Wiederherstellen sowie die Kosten für das Leeren aller 2D-Vorgänge bezahlt, und das Direct3D-Gerät wird noch nicht geleert. Um die Leistung zu erhöhen, beschränken Sie daher die Anzahl der Renderingoptionen zwischen Direct2D und Direct3D.

Ihr Pixelformat kennen

Wenn Sie ein Renderziel erstellen, können Sie die D2D1_PIXEL_FORMAT Struktur verwenden, um das Pixelformat und den Alphamodus anzugeben, der vom Renderziel verwendet wird. Ein Alphakanal ist Teil des Pixelformats, das den Abdeckungswert oder die Deckkraftinformationen angibt. Wenn ein Renderziel den Alphakanal nicht verwendet, sollte es mithilfe des D2D1_ALPHA_MODE_IGNORE Alphamodus erstellt werden. Dadurch wird die Zeit gespart, die für das Rendern eines Alpha-Kanals aufgewendet wird, der nicht benötigt wird.

Weitere Informationen zu Pixelformaten und Alphamodi finden Sie unter Unterstützte Pixelformate und Alphamodi.

Szenenkomplexität

Wenn Sie Leistungshotspots in einer Szene analysieren, die gerendert wird, ist es hilfreich zu wissen, ob die Szene füllratenbedingt oder vertexbedingt ist, da dies nützliche Informationen bereitstellen kann.

  • Füllrate: Die Füllrate bezieht sich auf die Anzahl der Pixel, die eine Grafikkarte pro Sekunde rendern und in den Videospeicher schreiben kann.
  • Vertex gebunden: Eine Szene ist vertexgebunden, wenn sie viele komplexe Geometrien enthält.

Grundlegendes zur Szenenkomplexität

Sie können ihre Szenenkomplexität analysieren, indem Sie die Größe des Renderziels ändern. Wenn Leistungssteigerungen für eine proportionale Verringerung der Größe des Rendering-Ziels sichtbar sind, ist die Anwendung an die Füllrate gebunden. Ansonsten ist die Szenenkomplexität der Leistungsengpass.

Wenn eine Szene durch die Füllrate begrenzt ist, kann die Verringerung der Größe des Renderziels die Leistung steigern. Dies liegt daran, dass die Anzahl der zu rendernden Pixel proportional mit der Größe des Renderziels reduziert wird.

Wenn eine Szene vertexgebunden ist, verringern Sie die Komplexität der Geometrie. Denken Sie aber daran, dass dies auf Kosten der Bildqualität erfolgt. Daher sollte eine sorgfältige Kompromissentscheidung zwischen der gewünschten Qualität und der erforderlichen Leistung getroffen werden.

Verbessern der Leistung für Direct2D-Druck-Apps

Direct2D bietet Kompatibilität mit dem Drucken. Sie können die gleichen Direct2D-Zeichnungsbefehle (in Form von Direct2D-Befehlslisten) zum Drucken an das Direct2D-Drucksteuerelement senden, wenn Sie nicht wissen, auf welche Geräte Sie zeichnen, oder wie die Zeichnung in den Druck übersetzt wird.

Sie können die Verwendung des Direct2D-Drucksteuerelements und Ihrer Direct2D-Zeichnungsbefehle weiter optimieren, um Druckergebnisse mit einer besseren Leistung zu erzielen.

Das Direct2D-Drucksteuerelement gibt Debugmeldungen aus, wenn ein Direct2D-Codemuster angezeigt wird, das zu einer geringeren Druckqualität oder -leistung führt (z. B. Codemuster, die weiter unten in diesem Thema aufgeführt sind), um Sie daran zu erinnern, wo Sie Leistungsprobleme vermeiden können. Um diese Debugmeldungen anzuzeigen, müssen Sie die Direct2D-Debugebene in Ihrem Code aktivieren. Anweisungen zum Aktivieren der Debugnachrichtenausgabe finden Sie unter Debugnachrichten .

Legen Sie die richtigen Eigenschaftswerte beim Erstellen der D2D-Drucksteuerung fest

Es gibt drei Eigenschaften, die Sie beim Erstellen des Direct2D-Drucksteuerelements festlegen können. Zwei dieser Eigenschaften wirken sich darauf aus, wie das Direct2D-Drucksteuerelement bestimmte Direct2D-Befehle verarbeitet und sich wiederum auf die Gesamtleistung auswirkt.

  • Modus für Schriftarten-Untergruppen: Die Direct2D-Drucksteuerung fasst die in jeder Seite verwendeten Schriftressourcen zusammen, bevor sie die Seite zum Drucken sendet. Dieser Modus reduziert die Größe der zum Drucken erforderlichen Seitenressourcen. Abhängig von der Schriftnutzung auf der Seite können Sie verschiedene Schriftartenuntermengemodi für die optimale Leistung auswählen.
    • D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT bietet in den meisten Fällen die beste Druckleistung. Wenn diese Einstellung auf diesen Modus festgelegt ist, verwendet das Direct2D-Drucksteuerelement eine heuristische Strategie, um zu entscheiden, wann Schriftarten untergeordnet werden sollen.
    • Für kurze Druckaufträge mit 1 oder 2 Seiten empfehlen wir D2D1_PRINT_FONT_SUBSET_MODE_EACHPAGE , bei dem die Direct2D Drucksteuerung eine Teilmenge von Schriftressourcen in jede Seite einbettet und diese Teilmenge nach dem Druck der Seite verwirft. Mit dieser Option wird sichergestellt, dass jede Seite sofort gedruckt werden kann, nachdem sie generiert wurde, aber die Größe der zum Drucken benötigten Seitenressourcen leicht zunimmt (in der Regel mit großen Schriftartenuntermengen).
    • Bei Druckaufträgen mit vielen Textseiten und kleinen Schriftgraden (z. B. 100 Seiten Text, die eine einzelne Schriftart verwenden), empfehlen wir D2D1_PRINT_FONT_SUBSET_MODE_NONE, wobei das Direct2D-Drucksteuerelement überhaupt keine Schriftartressourcen unterset. Stattdessen sendet sie die ursprünglichen Schriftartressourcen zusammen mit der Seite, die zuerst die Schriftart verwendet, und verwendet die Schriftartressourcen für spätere Seiten erneut, ohne sie erneut zu senden.
  • Raster-DPI: Wenn die Direct2D Drucksteuerung während der Direct2D-XPS-Konvertierung Direct2D-Befehle rastern muss, verwendet sie diesen DPI-Wert für die Rasterung. Anders ausgedrückt: Wenn die Seite keinen gerasterten Inhalt aufweist, ändert das Festlegen eines DPI-Werts die Leistung und Qualität nicht. Je nach Rasterungsnutzung auf der Seite können Sie unterschiedliche Rasterungs-DPIs für die optimale Balance zwischen Genauigkeit und Leistung auswählen.
    • 150 ist der Standardwert, wenn Sie beim Erstellen des Direct2D-Drucksteuerelements keinen Wert angeben. Dies ist in den meisten Fällen die beste Balance zwischen Druckqualität und Druckleistung.
    • Höhere DPI-Werte führen in der Regel zu einer besseren Druckqualität (da mehr Details erhalten bleiben), aber zu geringerer Leistung aufgrund der größeren Bitmaps, die entstehen. Es wird kein DPI-Wert empfohlen, der größer als 300 ist, da dadurch keine zusätzlichen Informationen visuell erkennbar durch menschliche Augen eingeführt werden.
    • Niedrigere DPI-Werte bedeuten möglicherweise eine bessere Leistung, können aber auch eine geringere Qualität erzeugen.

Vermeiden der Verwendung bestimmter Direct2D-Zeichnungsmuster

Es gibt Unterschiede zwischen dem, was Direct2D visuell darstellen kann und was das Drucksubsystem entlang der gesamten Druckpipeline verwalten und transportieren kann. Die Direct2D-Drucksteuerung überbrückt diese Lücken, indem sie Direct2D-Primitive, die das Drucksubsystem nicht nativ unterstützt, entweder annähert oder rastert. Eine solche Annäherung führt in der Regel zu geringerer Drucktreue, geringerer Druckleistung oder beidem. Auch wenn ein Kunde dieselben Zeichnungsmuster sowohl für das Bildschirm- als auch für das Druckrendering verwenden kann, ist es in allen Fällen nicht ideal. Es ist am besten, solche Direct2D-Grundtypen und -muster für den Druckpfad so weit wie möglich zu vermeiden oder selbst zu rasterisieren, wobei Sie die volle Kontrolle über die Qualität und die Größe der gerasterten Bilder haben.

Hier finden Sie eine Liste von Fällen, in denen die Druckleistung und -qualität nicht ideal ist, und Sie sollten den Codepfad für eine optimale Druckleistung variieren.

  • Vermeiden Sie die Verwendung eines anderen primitiven Mischmodus als D2D1_PRIMITIVE_BLEND_SOURCEOVER.
  • Vermeiden Sie die Verwendung von Kompositionsmodi beim Zeichnen eines anderen Bilds als D2D1_COMPOSITE_MODE_SOURCE_OVER und D2D1_COMPOSITE_MODE_DESTINATION_OVER.
  • Vermeiden Sie das Zeichnen einer GDI-Metadatei.
  • Vermeiden Sie es, eine Ebenenressource zu schieben, die den Quellhintergrund kopiert (Aufruf von PushLayer mit Übergabe von D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND an die D2D1_LAYER_PARAMETERS1 Struktur).
  • Vermeiden Sie die Erstellung eines Bitmap-Pinsels oder Bildpinsels mit D2D1_EXTEND_MODE_CLAMP. Wir empfehlen Ihnen, D2D1_EXTEND_MODE_MIRROR zu verwenden, wenn Ihnen die Pixel außerhalb der Bildbegrenzung völlig egal sind (z.B. wenn das an den Pinsel angehängte Bild bekanntermaßen größer ist als der gefüllte Zielbereich).
  • Vermeiden Sie das Zeichnen von Bitmaps mit perspektivischen Transformationen.

Zeichnen von Text auf direkte und einfache Weise

Direct2D verfügt über mehrere Optimierungen beim Rendern von Texten für eine bessere Leistung und/oder bessere visuelle Qualität. Aber nicht alle Optimierungen verbessern die Druckleistung und -qualität, da sich das Drucken auf Papier in der Regel in einem viel höheren DPI-Wert befindet, und das Drucken muss keine Szenarien wie Animation berücksichtigen. Daher empfehlen wir, den ursprünglichen Text oder die Glyphen direkt zu zeichnen und beim Erstellen der Befehlsliste zum Drucken eine der folgenden Optimierungen zu vermeiden.

  • Vermeiden Sie das Zeichnen von Text mit der FillOpacityMask-Methode .
  • Vermeiden Sie es, Text im aliasierten Modus zu zeichnen.

Zeichne die ursprünglichen Bitmaps nach Möglichkeit

Wenn es sich bei der Zielbitmap um eine JPEG-, PNG-, TIFF- oder JPEG-XR-Bitmap handelt, können Sie eine WIC-Bitmap entweder aus einer Datenträgerdatei oder aus einem Speicherdatenstrom erstellen und dann eine Direct2D-Bitmap aus dieser WIC-Bitmap mit ID2D1DeviceContext::CreateBitmapFromWicBitmap erstellen und schließlich diese Direct2D-Bitmap ohne weitere Manipulation direkt an das Direct2D-Drucksteuerelement übergeben. Dadurch kann das Direct2D-Drucksteuerelement den Bitmapdatenstrom wiederverwenden, was in der Regel zu einer besseren Druckleistung (durch Überspringen redundanter Bitmapcodierung und Decodierung) und einer besseren Druckqualität führt (wenn Metadaten wie Farbprofile in der Bitmap beibehalten werden).

Das Zeichnen der ursprünglichen Bitmap bietet den folgenden Vorteil für Anwendungen.

  • Im Allgemeinen behält Direct2D-Druck die ursprünglichen Informationen (ohne Verlust oder Rauschen) bis spät in der Pipeline bei, insbesondere wenn Apps die Details der Druckpipeline nicht kennen oder nicht wissen möchten, wie etwa welcher Drucker verwendet wird, welche DPI der Zieldrucker hat usw.
  • In vielen Fällen bedeutet die Verzögerung der Bitmaprasterung eine bessere Leistung (z. B. beim Drucken eines 96dpi-Fotos auf einem 600dpi-Drucker).
  • In bestimmten Fällen ist das Übergeben der originalen Bilder die einzige Möglichkeit, hohe Genauigkeit (z. B. eingebettete Farbprofile) zu berücksichtigen.

Sie können sich jedoch nicht für eine solche Optimierung entscheiden, da:

  • Durch die Abfrage von Druckerinformationen und die frühzeitige Rasterung können Sie die Inhalte selbst rastern, wobei Sie die volle Kontrolle über das endgültige Erscheinungsbild auf dem Papier haben.
  • In bestimmten Fällen kann die frühzeitige Rasterung die End-to-End-Leistung einer App (z. B. das Drucken von Fotos im Brieftaschenformat) verbessern.
  • In bestimmten Fällen erfordert das Übergeben der ursprünglichen Bitmaps eine erhebliche Änderung der vorhandenen Codearchitektur (z. B. Bildverzögerung beim Laden und Ressourcenaktualisierungspfade in bestimmten Anwendungen).

Schlussfolgerung

Obwohl Direct2D hardwarebeschleunigt ist und für hohe Leistung vorgesehen ist, müssen Sie die Features korrekt verwenden, um den Durchsatz zu maximieren. Die hier behandelten Techniken werden von der Untersuchung allgemeiner Szenarien abgeleitet und gelten möglicherweise nicht für alle Anwendungsszenarien.