Share via


Verbessern der Leistung von Direct2D-Apps

Obwohl Direct2D hardwarebeschleunigt ist und für hohe Leistung gedacht ist, müssen Sie die Features ordnungsgemäß verwenden, um den Durchsatz zu maximieren. Die hier gezeigten Techniken basieren auf der Untersuchung gängiger Szenarien und gelten möglicherweise nicht für alle App-Szenarien. Daher kann ein sorgfältiges Verständnis des App-Verhaltens und der Leistungsziele dazu beitragen, die gewünschten Ergebnisse zu erzielen.

Ressourcenauslastung

Eine Ressource ist eine Zuordnung irgendeiner 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. Das Erstellen und Löschen von Ressourcen auf Hardware sind kostspielige Vorgänge, da sie einen hohen Mehraufwand für die Kommunikation mit dem Video-Karte erfordern. Sehen wir uns an, wie Direct2D Inhalte für ein Ziel rendert.

In Direct2D werden alle Renderingbefehle zwischen einem Aufruf von BeginDraw und einem Aufruf von EndDraw eingeschlossen. Diese Aufrufe werden an ein Renderziel ausgeführt. 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 der folgenden Anweisungen zutrifft:

  • EndDraw ist aufgetreten. Wenn EndDraw aufgerufen wird, werden alle Batchzeichnungsvorgänge abgeschlossen und die status des Vorgangs zurückgegeben.
  • Sie führen einen expliziten Aufruf von Flush aus: Die Flush-Methode bewirkt, dass der Batch verarbeitet und alle ausstehenden Befehle ausgegeben werden.
  • Der Puffer, der die Renderingbefehle enthält, ist voll. Wenn dieser Puffer voll ist, bevor die beiden vorherigen Bedingungen erfüllt sind, werden die Renderingbefehle geleert.

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

Wiederverwenden von Ressourcen

Wie bereits erwähnt, ist das Erstellen und Löschen von Ressourcen auf hardwareintensiver Basis. Verwenden Sie also Ressourcen nach Möglichkeit wieder. Nehmen Sie das Beispiel für die Erstellung von Bitmaps in der Spieleentwicklung. Normalerweise werden Bitmaps, aus denen eine Szene in einem Spiel besteht, gleichzeitig mit allen verschiedenen Variationen erstellt, die für das spätere Frame-to-Frame-Rendering erforderlich sind. Zum Zeitpunkt des tatsächlichen Szenenrenderings und des erneuten Renderns werden diese Bitmaps wiederverwendet, anstatt neu zu erstellen.

Hinweis

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

 

Einschränken der Verwendung von flush

Da die Flush-Methode dazu führt, dass die Renderingbefehle im Batch verarbeitet werden, wird davon abgeraten. Behalten Sie in den meisten gängigen Szenarien direct2D die Ressourcenverwaltung bei.

Bitmaps

Wie bereits erwähnt, sind das Erstellen und Löschen von Ressourcen sehr kostspielige Vorgänge in Hardware. Eine Bitmap ist eine Art Ressource, die häufig verwendet wird. Das Erstellen von Bitmaps für das Video Karte ist teuer. Die Wiederverwendung kann dazu beitragen, die Anwendung schneller zu machen.

Erstellen großer Bitmaps

Grafikkarten weisen in der Regel eine Mindestgröße für die Speicherbelegung auf. Wenn eine Zuordnung angefordert wird, die kleiner als diese ist, wird eine Ressource dieser Mindestgröße zugeordnet, und der überschüssige Arbeitsspeicher wird verschwendet und steht für andere Dinge nicht zur Verfügung. Wenn Sie viele kleine Bitmaps benötigen, besteht eine bessere Technik darin, eine große Bitmap zuzuordnen und alle kleinen Bitmapinhalte in dieser großen Bitmap zu speichern. Dann können Unterbereiche der größeren Bitmap dort gelesen werden, wo die kleineren Bitmaps benötigt werden. Häufig sollten Sie Zwischenraum (transparente schwarze Pixel) zwischen den kleinen Bitmaps einschließen, um interaktionen zwischen den kleineren Bildern während vorgängen zu vermeiden. Dies wird auch als Atlas bezeichnet und hat den Vorteil, den Mehraufwand für die Bitmaperstellung und die Speicherverschwendung kleiner Bitmapzuordnungen zu reduzieren. Es wird empfohlen, die meisten Bitmaps auf mindestens 64 KB zu beschränken und die Anzahl der Bitmaps zu begrenzen, die kleiner als 4 KB sind.

Erstellen eines Atlass von Bitmaps

Es gibt einige gängige Szenarien, für die ein Bitmapatlas sehr gut geeignet ist. Kleine Bitmaps können in einer großen Bitmap gespeichert werden. Diese kleinen Bitmaps können bei Bedarf aus der größeren Bitmap abgerufen werden, indem Sie das Zielrechteck angeben. Beispielsweise muss eine Anwendung mehrere Symbole zeichnen. Alle Bitmaps, die den Symbolen zugeordnet sind, können im Voraus in eine große Bitmap geladen werden. Und zur Renderzeit 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, in dem sie gespeichert ist. Das Erstellen einer Bitmap, die größer ist, kann zu einem Fehler führen.

 

Hinweis

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

 

Erstellen freigegebener Bitmaps

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 Mehraufwand für die Leistung zu reduzieren.

Hinweis

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

 

Kopieren von Bitmaps

Das Erstellen einer DXGI-Oberfläche ist ein teurer Vorgang, daher können Sie vorhandene Oberflächen nach Möglichkeit wiederverwenden. Selbst in der Software ist es besser, diesen Teil zu aktualisieren, als die gesamte Bitmap wegzuwerfen und alles neu zu erstellen. Obwohl Sie CreateCompatibleRenderTarget verwenden können, um die gleichen Ergebnisse zu erzielen, ist das Rendern in der Regel ein viel teurerer Vorgang als das Kopieren. Dies liegt daran, dass die Hardware keine Bitmap in derselben Speicherreihenfolge speichert, in der die Bitmap adressiert wird, um die Cachelokalität zu verbessern. Stattdessen kann die Bitmap geschwengt werden. Das Schwenken wird von der CPU entweder durch den Treiber (der langsam ist und nur bei Unteren-End-Teilen verwendet wird) oder durch den Speicher-Manager auf der GPU ausgeblendet. Aufgrund von Einschränkungen, wie Daten beim Rendern in ein Renderziel geschrieben werden, werden Renderziele in der Regel nicht geschwemmt oder auf eine Weise geschwommen, die weniger optimal ist, als erreicht werden kann, wenn Sie wissen, dass Sie nie auf der Oberfläche rendern müssen. Daher werden die CopyFrom*-Methoden zum Kopieren von Rechtecken aus einer Quelle in die Direct2D-Bitmap bereitgestellt.

CopyFrom kann in einer der drei Formen verwendet werden:

Verwenden einer gekachelten Bitmap über Strichen

Das Rendern einer gestrichelten Linie ist aufgrund der hohen Qualität und Genauigkeit des zugrunde liegenden Algorithmus ein sehr teurer Vorgang. In den meisten Fällen, die keine geradlinigen Geometrien betreffen, kann der gleiche Effekt schneller generiert werden, indem gekachelte Bitmaps verwendet werden.

Allgemeine Richtlinien zum Rendern komplexer statischer Inhalte

Zwischenspeichern von Inhalten, wenn Sie denselben Inhalt frame over frame rendern, insbesondere wenn die Szene komplex ist.

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

  • Vollständiges Zwischenspeichern von Szenen mithilfe einer Farbbitte.
  • Pro primitiver Zwischenspeicherung mithilfe einer A8-Bitmap und der FillOpacityMask-Methode .
  • Pro primitives Zwischenspeichern mithilfe von Geometrierealisierungen.

Sehen wir uns die einzelnen details an.

Vollständiges Zwischenspeichern von Szenen mithilfe einer farblichen Bitmap

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

Hier sehen Sie 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());

In diesem Beispiel werden zwischengeschaltete Bitmaps zum Zwischenspeichern verwendet und die Bitmap umgeschaltet, auf die der Gerätekontext beim Rendern verweist. Dadurch wird vermieden, dass ein kompatibles Renderziel für denselben Zweck erstellt werden muss.

Pro primitiver Zwischenspeicherung mithilfe einer A8-Bitmap und der FillOpacityMask-Methode

Wenn die vollständige Szene nicht statisch ist, sondern aus Elementen wie Geometrie oder Text besteht, die statisch sind, können Sie ein pro primitives Zwischenspeicherungsverfahren verwenden. Diese Technik behält die Antialiasing-Eigenschaften des Primitiven, das zwischengespeichert wird, bei und arbeitet mit wechselnden Pinseltypen. Es verwendet eine A8-Bitmap, wobei A8 eine Art Pixelformat ist, das einen Alphakanal mit 8 Bit darstellt. A8-Bitmaps sind nützlich, um Geometrie/Text als Maske zu zeichnen. Wenn Sie die Deckkraft statischer Inhalte bearbeiten müssen, können Sie die Deckkraft der Maske übersetzen, drehen, verzerren oder skalieren, anstatt den Inhalt selbst zu manipulieren.

Hier sehen Sie 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);

Pro primitives Zwischenspeichern mithilfe von Geometrierealisierungen

Eine weitere Pro-Primitive-Zwischenspeicherungsmethode, die als Geometrierealisierungen bezeichnet wird, bietet mehr Flexibilität beim Umgang mit Geometrie. Wenn Sie aliasierte oder antialiasierte Geometrien wiederholt zeichnen möchten, ist es schneller, sie in Geometrierealisierungen zu konvertieren und die Realisierungen wiederholt zu zeichnen, als die Geometrien selbst wiederholt zu zeichnen. Geometrierealisierungen verbrauchen im Allgemeinen auch weniger Arbeitsspeicher als Deckkraftmasken (insbesondere bei großen Geometrien), und sie sind weniger empfindlich gegenüber Skalierungsänderungen. Weitere Informationen finden Sie unter Übersicht über Geometrierealisierungen.

Hier sehen Sie 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();

Geometrierendering

Verwenden eines bestimmten Zeichnengrundgrunds über Zeichnungsgeometrie

Verwenden Sie spezifischereprimitive Draw-Aufrufe wie DrawRectangle gegenüber generischen DrawGeometry-Aufrufen . Dies liegt daran, dass mit DrawRectangle die Geometrie bereits bekannt ist, sodass das Rendering schneller ist.

Rendern statischer Geometrie

Verwenden Sie in Szenarien, in denen die Geometrie statisch ist, die oben erläuterten Techniken für die zwischengespeicherte Pro-Primitive-Methode. Deckkraftmasken und Geometrierealisierungen können die Renderinggeschwindigkeit von Szenen, die statische Geometrie enthalten, erheblich verbessern.

Verwenden eines Multithreadgerätekontexts

Anwendungen, die erwarten, dass sie große Mengen komplexer geometrischer Inhalte rendern, 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 auf alle logischen Kerne, die auf dem System vorhanden sind, was die Gesamtrenderzeit erheblich verkürzen kann.

Hinweise:

  • Ab Windows 8.1 wirkt sich dieses Flag nur auf das Rendering der Pfadgeometrie aus. Es hat keine Auswirkungen auf Szenen, die nur andere primitive Typen (z. B. Text, Bitmaps oder Geometrierealisierungen) enthalten.
  • Dieses Flag hat auch keine Auswirkungen beim Rendern in Software (d. h. beim Rendern mit einem WARP Direct3D-Gerät). Zum Steuern von Software-Multithreading sollten Anrufer beim Erstellen des WARP Direct3D-Geräts das flag D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS verwenden.
  • Die Angabe dieses Flags kann den Arbeitsspitzensatz während des Renderings erhöhen und die Threadkonflikte in Anwendungen erhöhen, die bereits die Multithreadverarbeitung nutzen.

Zeichnen von Text mit Direct2D

Direct2D-Textrenderingfunktionen werden in zwei Teilen angeboten. Der erste Teil, der als ID2D1RenderTarget::D rawText und ID2D1RenderTarget::D rawTextLayout-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, ermöglicht die Rasterung für Kunden, die bereits die Position der zu rendernden Glyphen kennen. Die folgenden beiden allgemeinen Regeln können dazu beitragen, die Textleistung beim Zeichnen in Direct2D zu verbessern.

DrawTextLayout im Vergleich zu 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 für das RenderTarget, und DrawText erstellt ein DirectWrite Layout für den Aufrufer basierend auf den übergebenen Parametern. Wenn derselbe Text mehrmals gerendert werden muss, verwenden Sie DrawTextLayout anstelle von DrawText, da DrawText bei jedem Aufruf ein Layout erstellt.

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.

Caching

Verwenden Sie die vollständige Szenen- oder primitive Bitmapzwischenspeicherung wie beim Zeichnen anderer Grundtypen.

Ausschneiden einer beliebigen Form

Die 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 erhalten, indem Sie Ebenen mit einer Geometriemaske oder die FillGeometry-Methode mit einem Deckkraftpinsel verwenden.

Hier sehen Sie ein Beispiel, das eine Ebene verwendet:

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

Hier sehen Sie 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 für die Verwendung von Ebenen vorgenommen, und es wird empfohlen, nach Möglichkeit die Verwendung von Ebenen-APIs anstelle von FillGeometry 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 Ebenenressource und kann Ressourcen zwischen Ebenen und Effektdiagrammen gemeinsam nutzen.

Achsenorientierte Clips

Wenn der zu beschneidende Bereich an der Achse der Zeichnungsoberfläche ausgerichtet ist, anstatt an beliebiger Stelle. Dieser Fall eignet sich für die Verwendung eines Cliprechtecks anstelle einer Ebene. Der Leistungsgewinn ist mehr für aliasgeometrie als für antialiasierte Geometrie. Weitere Informationen zu achsenorientierten Clips finden Sie im Thema PushAxisAlignedClip .

DXGI-Interoperabilität: Vermeiden häufiger Wechsel

Direct2D kann nahtlos mit Direct3D-Oberflächen zusammenarbeiten. Dies ist sehr nützlich, um Anwendungen zu erstellen, die eine Mischung aus 2D- und 3D-Inhalten rendern. Aber jeder Wechsel zwischen dem Zeichnen von Direct2D- und Direct3D-Inhalten wirkt sich auf die Leistung aus.

Beim Rendern auf einer DXGI-Oberfläche speichert Direct2D den Zustand der Direct3D-Geräte beim Rendern und stellt ihn wieder her, wenn das Rendering abgeschlossen ist. Jedes Mal, wenn ein Batch des Direct2D-Renderings abgeschlossen ist, werden die Kosten für dieses Speichern und Wiederherstellen sowie die Kosten für das Leeren aller 2D-Vorgänge bezahlt, und dennoch wird das Direct3D-Gerät 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. Dies spart die Zeit, die für das Rendern eines nicht benötigten Alphakanals aufgewendet wird.

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

Szenenkomplexität

Wenn Sie Leistungshäufigkeitspunkte in einer Szene analysieren, die gerendert wird, kann das Wissen, ob die Szene Füllraten- oder Scheitelpunktbindung ist, nützliche Informationen liefern.

  • Füllrate: Die Füllrate bezieht sich auf die Anzahl von Pixeln, die eine Grafik Karte rendern und in den Videospeicher pro Sekunde schreiben kann.
  • Scheitelpunktbindung: Eine Szene ist scheitelpunktgebunden, wenn sie viele komplexe Geometrien enthält.

Grundlegendes zur Komplexität von Szenen

Sie können die Komplexität Ihrer Szene analysieren, indem Sie die Größe des Renderziels ändern. Wenn Leistungsgewinne für eine proportionale Verkleinerung des Renderziels sichtbar sind, ist die Anwendung Füllrate gebunden. Andernfalls ist die Szenenkomplexität der Leistungsengpass.

Wenn eine Szene Füllrate gebunden ist, kann die Reduzierung der Größe des Renderziels die Leistung verbessern. Dies liegt daran, dass die Anzahl der zu rendernden Pixel proportional zur Größe des Renderziels reduziert wird.

Wenn eine Szene scheitelpunktgebunden ist, reduzieren Sie die Komplexität der Geometrie. Denken Sie jedoch daran, dass dies auf Kosten der Bildqualität geschieht. 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 dieselben 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 Druck übersetzt wird.

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

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

Festlegen der richtigen Eigenschaftswerte beim Erstellen des D2D-Drucksteuerelements

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

  • Schriftartuntersetmodus: Das Direct2D-Drucksteuerelement setzt die auf jeder Seite verwendeten Schriftartressourcen unter, bevor es die zu druckende Seite sendet. Dieser Modus reduziert die Größe der seitenseitigen Ressourcen, die zum Drucken benötigt werden. Abhängig von der Schriftnutzung auf der Seite können Sie verschiedene Schriftartuntersetmodi auswählen, um die beste Leistung zu erzielen.
    • D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT bietet in den meisten Fällen die beste Druckleistung. Bei Festlegung auf diesen Modus 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 das Direct2D-Drucksteuerelement Schriftartressourcen auf jeder Seite unterlegt und einbettet, und dann diese Schriftartteilmenge verwirft, nachdem die Seite gedruckt wurde. Diese Option stellt sicher, dass jede Seite sofort nach der Generierung gedruckt werden kann, erhöht jedoch die Größe der für den Druck benötigten Seitenressourcen geringfügig (mit in der Regel großen Schriftteilmengen).
    • Für Druckaufträge 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 die Schriftartressourcen überhaupt nicht untergeordnet. stattdessen werden die ursprünglichen Schriftartressourcen zusammen mit der Seite gesendet, auf der die Schriftart zuerst verwendet wird, und die Schriftartressourcen für spätere Seiten erneut verwendet, ohne sie erneut zu senden.
  • Rasterungs-DPI: Wenn das Direct2D-Drucksteuerelement Direct2D-Befehle während der Direct2D-XPS-Konvertierung rastern muss, verwendet es diesen DPI für die Rasterung. Mit anderen Worten, wenn die Seite keinen gerasterten Inhalt enthält, ändert das Festlegen von DPI keine Leistung und Qualität. Abhängig von der Rasterungsverwendung auf der Seite können Sie verschiedene Rasterungs-DPIs auswählen, um ein optimales Gleichgewicht zwischen Genauigkeit und Leistung zu erzielen.
    • 150 ist der Standardwert, wenn Sie beim Erstellen des Direct2D-Drucksteuerelements keinen Wert angeben, was in den meisten Fällen die beste Balance zwischen Druckqualität und Druckleistung darstellt.
    • Höhere DPI-Werte führen in der Regel zu einer besseren Druckqualität (da mehr Details beibehalten werden), aber aufgrund der größeren Bitmaps, die sie generiert, zu einer geringeren Leistung. Wir empfehlen keinen DPI-Wert größer als 300, da dadurch keine zusätzlichen Informationen eingeführt werden, die für menschliche Augen sichtbar sind.
    • Niedrigere DPI-Werte können eine bessere Leistung bedeuten, können aber auch zu einer niedrigeren Qualität führen.

Vermeiden bestimmter Direct2D-Zeichnungsmuster

Es gibt Unterschiede zwischen dem, was Direct2D visuell darstellen kann, und dem, was das Drucksubsystem verwalten und entlang der gesamten Druckpipeline transportieren kann. Das Direct2D-Drucksteuerelement überbrückt diese Lücken, indem direct2D-Grundtypen, die vom Drucksubsystem nicht nativ unterstützt werden, entweder nähern oder rastern. Eine solche Näherung führt in der Regel zu einer geringeren Druckgenauigkeit, einer geringeren Druckleistung oder beidem. Obwohl ein Kunde die gleichen Zeichnungsmuster sowohl für das Bildschirm- als auch für das Druckrendering verwenden kann, ist dies nicht in allen Fällen ideal. Es ist am besten, solche Direct2D-Grundtypen und Muster nicht so weit wie möglich für den Druckpfad zu verwenden, oder Sie besitzen die Rasterung, bei der Sie die volle Kontrolle über die Qualität und die Größe der gerasterten Bilder haben.

Im Folgenden finden Sie eine Liste von Fällen, in denen die Druckleistung und -qualität nicht ideal sind und sie möglicherweise den Codepfad für eine optimale Druckleistung variieren möchten.

  • 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 das Pushen einer Ebenenressource, die den Quellhintergrund kopiert (Aufrufen von PushLayer mit Übergabe D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND an die D2D1_LAYER_PARAMETERS1-Struktur ).
  • Vermeiden Sie das Erstellen von Bitmappinsel oder Bildpinsel mit D2D1_EXTEND_MODE_CLAMP. Es wird empfohlen, D2D1_EXTEND_MODE_MIRROR zu verwenden, wenn Pixel außerhalb des bildgebundenen Bilds überhaupt nicht wichtig sind (z. B. ist bekannt, dass das an den Pinsel angefügte Bild größer als der gefüllte Zielbereich ist).
  • Vermeiden Sie das Zeichnen von Bitmaps mit Perspektivtransformationen.

Text direkt und einfach zeichnen

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 das Drucken auf Papier in der Regel in einem viel höheren DPI-Wert erfolgt und das Drucken keine Szenarien wie Animationen berücksichtigen muss. Daher wird empfohlen, den Originaltext oder die Glyphen direkt zu zeichnen und beim Erstellen der Befehlsliste für den Druck eine der folgenden Optimierungen zu vermeiden.

  • Vermeiden Sie das Zeichnen von Text mit der FillOpacityMask-Methode .
  • Vermeiden Sie das Zeichnen von Text im Aliasmodus.

Zeichnen Sie nach Möglichkeit die ursprünglichen Bitmaps.

Wenn es sich bei der Ziel-Bitmap um eine JPEG-, PNG-, TIFF- oder JPEG-XR-Bitmap handelt, können Sie eine WIC-Bitmap entweder aus einer Datenträgerdatei oder aus einem In-Memory-Stream erstellen, dann eine Direct2D-Bitmap aus dieser WIC-Bitmap mithilfe von ID2D1DeviceContext::CreateBitmapFromWicBitmap erstellen und diese Direct2D-Bitmap schließlich direkt ohne weitere Manipulation an das Direct2D-Drucksteuerelement übergeben. Auf diese Weise 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 (wenn Metadaten, z. B. 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) (z. B. auf welchem Drucker er druckt, welcher DPI der Zieldrucker ist usw.).
  • In vielen Fällen bedeutet die Verzögerung der Bitmaprasterung eine bessere Leistung (z. B. beim Drucken eines 96 dpi-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.

Eine solche Optimierung können Sie jedoch nicht aktivieren, weil:

  • Durch Abfragen von Druckerinformationen und frühzeitiger Rasterung können Sie Inhalte selbst rastern, wobei Sie die vollständige Kontrolle über die endgültige Darstellung auf dem Papier haben.
  • In bestimmten Fällen kann die frühe Rasterung die End-to-End-Leistung einer App verbessern (z. B. das Drucken von Fotos im Brieftaschenformat).
  • In bestimmten Fällen erfordert das Übergeben der ursprünglichen Bitmaps eine erhebliche Änderung der vorhandenen Codearchitektur (z. B. Das Laden von Bildern und Ressourcenupdatepfade, die in bestimmten Anwendungen gefunden werden).

Zusammenfassung

Obwohl Direct2D hardwarebeschleunigt ist und für hohe Leistung gedacht ist, müssen Sie die Features ordnungsgemäß verwenden, um den Durchsatz zu maximieren. Die hier behandelten Techniken basieren auf der Untersuchung allgemeiner Szenarien und gelten möglicherweise nicht für alle Anwendungsszenarien.