Condividi tramite


Miglioramento delle prestazioni delle app Direct2D

Anche se Direct2D è accelerato dall'hardware ed è destinato a prestazioni elevate, è necessario usare correttamente le funzionalità per ottimizzare la velocità effettiva. Le tecniche illustrate di seguito sono derivate dallo studio di scenari comuni e potrebbero non essere applicabili a tutti gli scenari dell'app. Pertanto, un'attenta comprensione del comportamento e degli obiettivi delle prestazioni dell'app può aiutare a raggiungere i risultati desiderati.

Utilizzo delle risorse

Una risorsa è un'allocazione di qualche tipo, in memoria video o di sistema. Le bitmap e i pennelli sono esempi di risorse.

In Direct2D le risorse possono essere create sia nel software che nell'hardware. La creazione e l'eliminazione delle risorse sull'hardware sono operazioni costose perché richiedono un sacco di sovraccarico per la comunicazione con la scheda video. Vediamo come Direct2D esegue il rendering del contenuto in una destinazione.

In Direct2D tutti i comandi di rendering sono racchiusi tra una chiamata a BeginDraw e una chiamata a EndDraw. Queste chiamate vengono effettuate a una destinazione di rendering. Prima di chiamare le operazioni di rendering, è necessario chiamare il metodo BeginDraw . Dopo aver chiamato BeginDraw , un contesto in genere compila un batch di comandi di rendering, ma ritarda l'elaborazione di questi comandi fino a quando una di queste istruzioni è true:

  • EndDraw si è verificato. Quando EndDraw viene chiamato, le operazioni di disegno in batch vengono completate e restituisce lo stato dell'operazione.
  • Si effettua una chiamata esplicita a Flush: il metodo Flush causa l'elaborazione del batch e tutti i comandi in sospeso devono essere emessi.
  • Il buffer che contiene i comandi di rendering è pieno. Se questo buffer diventa pieno prima che vengano soddisfatte le due condizioni precedenti, i comandi di rendering vengono scaricati.

Fino a quando le primitive non vengono scaricate, Direct2D mantiene riferimenti interni alle risorse corrispondenti, ad esempio bitmap e pennelli.

Riutilizzare le risorse

Come già accennato, la creazione e l'eliminazione delle risorse è costosa sull'hardware. Quindi riutilizzare le risorse quando possibile. Prendere l'esempio di creazione bitmap nello sviluppo di giochi. In genere, le bitmap che costituiscono una scena in un gioco vengono create contemporaneamente con tutte le diverse varianti necessarie per il rendering frame-to-frame successivo. Al momento del rendering effettivo della scena e del rendering, queste bitmap vengono riutilizzate anziché ricreate.

Nota

Non è possibile riutilizzare le risorse per l'operazione di ridimensionamento della finestra. Quando viene ridimensionata una finestra, alcune risorse dipendenti dalla scalabilità, ad esempio le destinazioni di rendering compatibili e probabilmente alcune risorse di livello devono essere ricreate perché il contenuto della finestra deve essere ridisegnato. Ciò può essere importante per mantenere la qualità complessiva della scena di cui è stato eseguito il rendering.

 

Limitare l'uso di scaricamento

Poiché il metodo Flush causa l'elaborazione dei comandi di rendering in batch, è consigliabile non usarlo. Per gli scenari più comuni, lasciare direct2D la gestione delle risorse.

Bitmap

Come accennato in precedenza, la creazione e l'eliminazione delle risorse sono operazioni molto costose nell'hardware. Una bitmap è un tipo di risorsa usata spesso. La creazione di bitmap sulla scheda video è costosa. Riusarli può aiutare a rendere più veloce l'applicazione.

Creare bitmap di grandi dimensioni

Le schede video in genere hanno dimensioni minime di allocazione della memoria. Se viene richiesta un'allocazione minore di questa, viene allocata una risorsa di questa dimensione minima e la memoria in eccedenza viene sprecata e non disponibile per altre cose. Se sono necessarie molte bitmap di piccole dimensioni, una tecnica migliore consiste nell'allocare una bitmap di grandi dimensioni e archiviare tutti i contenuti bitmap di piccole dimensioni in questa bitmap di grandi dimensioni. È quindi possibile leggere sottoareas della bitmap più grande in cui sono necessarie le bitmap più piccole. Spesso è necessario includere spaziatura interna (pixel neri trasparenti) tra le piccole bitmap per evitare qualsiasi interazione tra le immagini più piccole durante le operazioni. Questo è noto anche come atlas e ha il vantaggio di ridurre il sovraccarico di creazione bitmap e lo spreco di memoria di piccole allocazioni bitmap. È consigliabile mantenere la maggior parte delle bitmap almeno 64 KB e limitare il numero di bitmap inferiori a 4 KB.

Creare un atlas di bitmap

Esistono alcuni scenari comuni per i quali un atlas bitmap può servire molto bene. Le bitmap di piccole dimensioni possono essere archiviate all'interno di una bitmap di grandi dimensioni. Queste piccole bitmap possono essere estratte dalla bitmap più grande quando sono necessarie specificando il rettangolo di destinazione. Ad esempio, un'applicazione deve disegnare più icone. Tutte le bitmap associate alle icone possono essere caricate in una bitmap di grandi dimensioni in primo piano. E in fase di rendering, possono essere recuperati dalla bitmap di grandi dimensioni.

Nota

Una bitmap Direct2D creata in memoria video è limitata alle dimensioni massime della bitmap supportate dalla scheda in cui è archiviata. La creazione di una bitmap più grande di quella potrebbe causare un errore.

 

Nota

A partire da Windows 8, Direct2D include un effetto Atlas che può semplificare questo processo.

 

Creare bitmap condivise

La creazione di bitmap condivise consente ai chiamanti avanzati di creare oggetti bitmap Direct2D supportati direttamente da un oggetto esistente, già compatibile con la destinazione di rendering. In questo modo si evita di creare più superfici e di ridurre il sovraccarico delle prestazioni.

Nota

Le bitmap condivise sono in genere limitate alle destinazioni software o alle destinazioni interoperabili con DXGI. Usare i metodi CreateBitmapFromDxgiSurface, CreateBitmapFromWicBitmap e CreateSharedBitmap per creare bitmap condivise.

 

Copia di bitmap

La creazione di una superficie DXGI è un'operazione costosa, in modo da riutilizzare le superfici esistenti quando è possibile. Anche nel software, se una bitmap è per lo più nel formato desiderato, ad eccezione di una piccola parte, è preferibile aggiornare tale parte rispetto a generare l'intera bitmap via e ricreare tutto. Sebbene sia possibile usare CreateCompatibleRenderTarget per ottenere gli stessi risultati, il rendering è in genere un'operazione molto più costosa rispetto alla copia. Ciò è dovuto al fatto che, per migliorare la località della cache, l'hardware non archivia effettivamente una bitmap nello stesso ordine di memoria a cui viene indirizzata la bitmap. Al contrario, la bitmap potrebbe essere swizzled. Lo scorrimento rapido è nascosto dalla CPU dal driver (che è lento e usato solo nelle parti di fascia inferiore) o dal gestore della memoria nella GPU. A causa dei vincoli sul modo in cui i dati vengono scritti in una destinazione di rendering durante il rendering, le destinazioni di rendering in genere non vengono swizzled o swizzled in modo meno ottimale di quanto si possa ottenere se si sa che non è mai necessario eseguire il rendering sulla superficie. Di conseguenza, i metodi CopyFrom* vengono forniti per copiare rettangoli da un'origine alla bitmap Direct2D.

CopyFrom può essere usato in una delle tre forme seguenti:

Usare la bitmap affiancata sull'shing

Il rendering di una linea tratteggiata è un'operazione molto costosa a causa dell'elevata qualità e accuratezza dell'algoritmo sottostante. Per la maggior parte dei casi che non coinvolgono geometrie rectilineari, lo stesso effetto può essere generato più velocemente usando bitmap affiancate.

Linee guida generali per il rendering di contenuto statico complesso

Memorizzare nella cache il contenuto se si esegue il rendering dello stesso frame di contenuto su frame, soprattutto quando la scena è complessa.

Esistono tre tecniche di memorizzazione nella cache che è possibile usare:

  • Memorizzazione nella cache completa della scena tramite una bitmap a colori.
  • Memorizzazione nella cache per primitiva usando una bitmap A8 e il metodo FillOpacityMask .
  • Memorizzazione nella cache per primitiva usando le realizzazione geometry.

Esaminiamo ognuna di queste informazioni in modo più dettagliato.

Memorizzazione nella cache completa della scena con una bitmap a colori

Quando si esegue il rendering di contenuto statico, in scenari come l'animazione, creare un'altra bitmap a colori intero anziché scrivere direttamente nella bitmap dello schermo. Salvare la destinazione corrente, impostare la destinazione sulla bitmap intermedia ed eseguire il rendering del contenuto statico. Tornare quindi alla bitmap dello schermo originale e disegnare la bitmap intermedia.

Ecco un esempio:

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

Questo esempio usa bitmap intermedie per la memorizzazione nella cache e commuta la bitmap a cui punta il contesto del dispositivo durante il rendering. In questo modo si evita la necessità di creare una destinazione di rendering compatibile per lo stesso scopo.

Memorizzazione nella cache per primitiva usando una bitmap A8 e il metodo FillOpacityMask

Quando la scena completa non è statica, ma è costituita da elementi come geometria o testo statici, è possibile usare una tecnica di memorizzazione nella cache per primitiva. Questa tecnica mantiene le caratteristiche anti-aliasing della primitiva memorizzata nella cache e funziona con i tipi di pennello modificati. Usa una bitmap A8 in cui A8 è un tipo di formato pixel che rappresenta un canale alfa con 8 bit. Le bitmap A8 sono utili per disegnare geometria/testo come maschera. Quando è necessario modificare l'opacità del contenuto statico, anziché modificare il contenuto stesso, è possibile tradurre, ruotare, asimmetrie o ridimensionare l'opacità della maschera.

Ecco un esempio:

// 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);

Memorizzazione nella cache per primitiva usando le realizzazioni geometry

Un'altra tecnica di memorizzazione nella cache per primitiva, denominata realizzazione della geometria, offre una maggiore flessibilità durante la gestione della geometria. Quando si desidera disegnare ripetutamente geometrie con alias o anti-aliasing, è più veloce convertirle in realizzazione geometriche e disegnare ripetutamente le realizzazioni rispetto a disegnare ripetutamente le geometrie stesse. Le realizzazioni geometriche utilizzano in genere meno memoria delle maschere di opacità (soprattutto per geometrie di grandi dimensioni) e sono meno sensibili alle modifiche in scala. Per altre informazioni, vedere Cenni preliminari sulla realizzazione della geometria.

Ecco un esempio:

    // 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 della geometria

Usare una primitiva di disegno specifica sulla geometria di disegno

Usare chiamateprimitive di disegno più specifiche, ad esempio DrawRectangle , su chiamate DrawGeometry generiche. Ciò è dovuto al fatto che con DrawRectangle la geometria è già nota, quindi il rendering è più veloce.

Rendering della geometria statica

Negli scenari in cui la geometria è statica, usare le tecniche di memorizzazione nella cache per primitive illustrate in precedenza. Le maschere di opacità e le realizzazione della geometria possono migliorare notevolmente la velocità di rendering delle scene che contengono geometria statica.

Usare un contesto di dispositivo multithreading

Le applicazioni che prevedono di eseguire il rendering di quantità significative di contenuto geometrico complesso devono considerare la possibilità di specificare il flag D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTI_THREADED_OPTIMIZATIONS durante la creazione di un contesto di dispositivo Direct2D . Quando viene specificato questo flag, Direct2D distribuirà il rendering in tutti i core logici presenti nel sistema, riducendo in modo significativo il tempo di rendering complessivo.

Note:

  • A partire da Windows 8.1, questo flag influisce solo sul rendering della geometria del percorso. Non ha alcun impatto sulle scene contenenti solo altri tipi primitivi (ad esempio testo, bitmap o realizzazione geometry).
  • Questo flag non ha alcun impatto anche durante il rendering nel software(ad esempio quando si esegue il rendering con un dispositivo WARP Direct3D). Per controllare il multithreading software, i chiamanti devono usare il flag D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS durante la creazione del dispositivo WARP Direct3D.
  • La specifica di questo flag può aumentare il working set di picco durante il rendering e può anche aumentare la contesa di thread nelle applicazioni che sfruttano già l'elaborazione multithreading.

Disegno di testo con Direct2D

La funzionalità di rendering del testo Direct2D è disponibile in due parti. La prima parte, esposta come metodo ID2D1RenderTarget::D rawText e ID2D1RenderTarget::D rawTextLayout , consente a un chiamante di passare parametri di stringa e formattazione o di layout di testo DWrite per più formati. Deve essere adatto per la maggior parte dei chiamanti. Il secondo modo per eseguire il rendering del testo, esposto come metodo ID2D1RenderTarget::D rawGlyphRun , fornisce rasterizzazione per i clienti che conoscono già la posizione dei glifi di cui vogliono eseguire il rendering. Le due regole generali seguenti consentono di migliorare le prestazioni del testo durante il disegno in Direct2D.

DrawTextLayout e DrawText

Sia DrawText che DrawTextLayout consentono a un'applicazione di eseguire facilmente il rendering del testo formattato dall'API DirectWrite. DrawTextLayout disegna un oggetto DWriteTextLayout esistente nel RenderTarget e DrawText costruisce un layout DirectWrite per il chiamante, in base ai parametri passati. Se il rendering dello stesso testo deve essere eseguito più volte, usare DrawTextLayout anziché DrawText, perché DrawText crea un layout ogni volta che viene chiamato.

Scelta della modalità di rendering del testo corretta

Impostare la modalità antialias di testo su D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE in modo esplicito. La qualità del rendering del testo in scala di grigi è paragonabile a ClearType, ma è molto più veloce.

Memorizzazione nella cache

Usare la scena completa o la memorizzazione nella cache bitmap primitiva, ad esempio con il disegno di altre primitive.

Ritaglio di una forma arbitraria

La figura mostra il risultato dell'applicazione di una clip a un'immagine.

immagine che mostra un esempio di immagine prima e dopo una clip.

È possibile ottenere questo risultato usando i livelli con una maschera geometry o il metodo FillGeometry con un pennello di opacità.

Ecco un esempio che usa un livello:

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

Ecco un esempio che usa il metodo FillGeometry :

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

In questo esempio di codice, quando chiami il metodo PushLayer, non passi un livello creato dall'app. Direct2D crea automaticamente un livello. Direct2D è in grado di gestire l'allocazione e la distruzione di questa risorsa senza alcun coinvolgimento dell'app. In questo modo Direct2D può riutilizzare i livelli internamente e applicare ottimizzazioni di gestione delle risorse.

In Windows 8 sono state apportate molte ottimizzazioni all'utilizzo dei livelli ed è consigliabile provare a usare le API di livello anziché FillGeometry quando possibile.

PushLayer in Windows 8

L'interfaccia ID2D1DeviceContext deriva dall'interfaccia ID2D1RenderTarget ed è fondamentale per visualizzare il contenuto Direct2D in Windows 8, per altre informazioni su questa interfaccia, vedere Dispositivi e contesti di dispositivo. Con l'interfaccia del contesto del dispositivo, è possibile ignorare la chiamata al metodo CreateLayer e quindi passare NULL al metodo ID2D1DeviceContext::P ushLayer . Direct2D gestisce automaticamente la risorsa del livello e può condividere le risorse tra livelli ed effetti grafici.

Clip allineate all'asse

Se l'area da ritagliare è allineata all'asse della superficie di disegno anziché arbitraria. Questo caso è adatto per l'uso di un rettangolo di clip anziché di un livello. Il miglioramento delle prestazioni è maggiore per la geometria aliasata rispetto alla geometria antialiased. Per altre informazioni sulle clip allineate sull'asse, vedere l'argomento PushAxisAlignedClip .

Interoperabilità DXGI: evitare commutatori frequenti

Direct2D può interagire senza problemi con le superfici Direct3D. Questo è molto utile per la creazione di applicazioni che eseguono il rendering di una combinazione di contenuto 2D e 3D. Ogni commutatore tra il disegno Direct2D e il contenuto Direct3D influisce sulle prestazioni.

Quando si esegue il rendering in una superficie DXGI, Direct2D salva lo stato dei dispositivi Direct3D durante il rendering e lo ripristina al termine del rendering. Ogni volta che viene completato un batch di rendering Direct2D, il costo di questo salvataggio e ripristino e il costo di scaricare tutte le operazioni 2D vengono ancora pagate e il dispositivo Direct3D non viene scaricato. Pertanto, per aumentare le prestazioni, limitare il numero di commutatori di rendering tra Direct2D e Direct3D.

Conoscere il formato pixel

Quando si crea una destinazione di rendering, è possibile usare la struttura D2D1_PIXEL_FORMAT specificare il formato pixel e la modalità alfa utilizzata dalla destinazione di rendering. Un canale alfa fa parte del formato pixel che specifica il valore di copertura o le informazioni sull'opacità. Se una destinazione di rendering non usa il canale alfa, deve essere creata usando la modalità alfa D2D1_ALPHA_MODE_IGNORE . Questo consente di risparmiare tempo per il rendering di un canale alfa che non è necessario.

Per altre informazioni sui formati pixel e sulle modalità alfa, vedere Formati pixel supportati e modalità alfa.

Complessità della scena

Quando si analizzano i punti caldi delle prestazioni in una scena che verrà eseguito il rendering, sapendo se la scena è associata a riempimento o vertice può fornire informazioni utili.

  • Frequenza di riempimento: la frequenza di riempimento fa riferimento al numero di pixel che una scheda grafica può eseguire il rendering e scrivere nella memoria video al secondo.
  • Limite vertice: una scena è associata al vertice quando contiene un sacco di geometria complessa.

Comprendere la complessità della scena

È possibile analizzare la complessità della scena modificando le dimensioni della destinazione di rendering. Se i miglioramenti delle prestazioni sono visibili per una riduzione proporzionale delle dimensioni della destinazione di rendering, l'applicazione è associata alla frequenza di riempimento. In caso contrario, la complessità della scena è il collo di bottiglia delle prestazioni.

Quando una scena è associata alla frequenza di riempimento, la riduzione delle dimensioni della destinazione di rendering può migliorare le prestazioni. Questo perché il numero di pixel da eseguire per il rendering verrà ridotto proporzionalmente con le dimensioni della destinazione di rendering.

Quando una scena è associata al vertice, ridurre la complessità della geometria. Ma ricorda che questa operazione viene eseguita a spese della qualità dell'immagine. Pertanto, una decisione attenta di compromesso deve essere presa tra la qualità desiderata e le prestazioni necessarie.

Miglioramento delle prestazioni per le app di stampa Direct2D

Direct2D offre compatibilità con la stampa. È possibile inviare gli stessi comandi di disegno Direct2D (sotto forma di elenchi di comandi Direct2D) al controllo di stampa Direct2D per la stampa, se non si conosce i dispositivi a cui si sta disegnando o come il disegno viene convertito nella stampa.

È possibile ottimizzare ulteriormente l'utilizzo del controllo di stampa Direct2D e dei comandi di disegno Direct2D per offrire risultati di stampa migliori.

Il controllo di stampa Direct2D restituisce i messaggi di debug quando vede un modello di codice Direct2D che porta a una qualità o prestazioni di stampa inferiori (ad esempio, i modelli di codice elencati più avanti in questo argomento) per ricordare dove è possibile evitare problemi di prestazioni. Per visualizzare questi messaggi di debug, è necessario abilitare Il livello di debug Direct2D nel codice. Per istruzioni per abilitare l'output dei messaggi di debug, vedere Eseguire il debug dei messaggi .

Impostare i valori di proprietà corretti quando si crea il controllo di stampa D2D

Sono disponibili tre proprietà che è possibile impostare quando si crea il controllo di stampa Direct2D . Due di queste proprietà influisce sul modo in cui il controllo di stampa Direct2D gestisce determinati comandi Direct2D e a sua volta influisce sulle prestazioni complessive.

  • Modalità subset carattere: il controllo di stampa Direct2D subset le risorse del carattere usate in ogni pagina prima di inviare la pagina da stampare. Questa modalità riduce le dimensioni delle risorse di pagina necessarie per stampare. A seconda dell'utilizzo dei tipi di carattere nella pagina, è possibile scegliere diverse modalità subset di caratteri per ottenere prestazioni ottimali.
    • D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT offre le migliori prestazioni di stampa nella maggior parte dei casi. Se impostato su questa modalità, il controllo di stampa Direct2D usa una strategia euristica per decidere quando impostare i tipi di carattere secondari.
    • Per i processi di stampa brevi con 1 o 2 pagine, è consigliabile D2D1_PRINT_FONT_SUBSET_MODE_EACHPAGE , dove il sottoinsieme del controllo di stampa Direct2D e incorpora le risorse dei tipi di carattere in ogni pagina, quindi elimina il subset di carattere dopo le stampe della pagina. Questa opzione assicura che ogni pagina possa essere stampata immediatamente dopo la generazione, ma aumenta leggermente le dimensioni delle risorse di pagina necessarie per la stampa (con in genere subset di caratteri di grandi dimensioni).
    • Per i processi di stampa con molte pagine di testo e dimensioni di caratteri di piccole dimensioni (come 100 pagine di testo che usano un singolo tipo di carattere), è consigliabile D2D1_PRINT_FONT_SUBSET_MODE_NONE, dove il controllo di stampa Direct2D non subset le risorse del tipo di carattere; invia invece le risorse del tipo di carattere originali insieme alla pagina che usa prima il tipo di carattere e usa di nuovo le risorse del tipo di carattere per le pagine successive senza eseguirne nuovamente il ripristino.
  • DPI di rasterizzazione: quando il controllo di stampa Direct2D deve rasterizzare i comandi Direct2D durante la conversione Direct2D-XPS, usa questo DPI per la rasterizzazione. In altre parole, se la pagina non ha alcun contenuto rasterizzato, l'impostazione di qualsiasi DPI non cambierà le prestazioni e la qualità. A seconda dell'utilizzo della rasterizzazione nella pagina, è possibile scegliere diversi DPI di rasterizzazione per il migliore equilibrio tra fedeltà e prestazioni.
    • 150 è il valore predefinito se non si specifica un valore quando si crea il controllo di stampa Direct2D , che è il migliore equilibrio tra qualità di stampa e prestazioni di stampa nella maggior parte dei casi.
    • I valori DPI più elevati comportano in genere una migliore qualità di stampa (come nei dettagli mantenuti) ma prestazioni inferiori a causa delle bitmap più grandi generate. Non è consigliabile alcun valore DPI maggiore di 300 perché non introduce informazioni aggiuntive visivamente percepibili dagli occhi umani.
    • Il valore DPI inferiore può significare prestazioni migliori, ma può anche produrre una qualità inferiore.

Evitare di usare determinati modelli di disegno Direct2D

Esistono differenze tra quello che Direct2D può rappresentare visivamente e ciò che il sottosistema di stampa può gestire e trasportare lungo tutta la pipeline di stampa. Il controllo di stampa Direct2D consente di colmare tali lacune in modo approssimativo o rasterizzare le primitive Direct2D che il sottosistema di stampa non supporta in modo nativo. Questa approssimazione comporta in genere prestazioni di stampa inferiori, prestazioni di stampa inferiori o entrambe. Pertanto, anche se un cliente può usare gli stessi modelli di disegno per il rendering dello schermo e della stampa, non è ideale in tutti i casi. È consigliabile non usare primitive e modelli Direct2D il più possibile per il percorso di stampa o per eseguire la propria rasterizzazione in cui si ha il controllo completo della qualità e delle dimensioni delle immagini rasterizzate.

Di seguito è riportato un elenco di casi in cui le prestazioni di stampa e la qualità non saranno ideali e potrebbe essere consigliabile considerare la variabile del percorso del codice per prestazioni di stampa ottimali.

  • Evitare di usare la modalità di fusione primitiva diversa da D2D1_PRIMITIVE_BLEND_SOURCEOVER.
  • Evitare di usare le modalità di composizione quando si disegna un'immagine diversa da D2D1_COMPOSITE_MODE_SOURCE_OVER e D2D1_COMPOSITE_MODE_DESTINATION_OVER.
  • Evitare di disegnare un meta file GDI.
  • Evitare di eseguire il push di una risorsa di livello che copia lo sfondo dell'origine (chiamando PushLayer con il passaggio di D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND allo struct D2D1_LAYER_PARAMETERS1 ).
  • Evitare di creare pennello bitmap o pennello immagine con D2D1_EXTEND_MODE_CLAMP. È consigliabile usare D2D1_EXTEND_MODE_MIRROR se non ci si preoccupa dei pixel esterni all'immagine associata a tutti (ad esempio, l'immagine associata al pennello è nota per essere più grande dell'area di destinazione riempita).
  • Evitare bitmap di disegno con trasformazioni di prospettiva.

Disegna testo in modo diretto e normale

Direct2D offre diverse ottimizzazioni durante il rendering dei testi da visualizzare per migliorare le prestazioni e/o migliorare la qualità visiva. Ma non tutte le ottimizzazioni migliorano le prestazioni di stampa e la qualità poiché la stampa su carta è in genere in un valore DPI molto più elevato e la stampa non deve soddisfare scenari come l'animazione. È quindi consigliabile disegnare direttamente il testo o glifi originali ed evitare qualsiasi delle ottimizzazioni seguenti durante la creazione dell'elenco di comandi per la stampa.

  • Evitare il testo di disegno con il metodo FillOpacityMask .
  • Evitare il testo di disegno in modalità alias.

Disegna le bitmap originali quando possibile

Se la bitmap di destinazione è una bitmap JPEG, PNG, TIFF o JPEG-XR, è possibile creare una bitmap WIC da un file disco o da un flusso in memoria, quindi creare una bitmap Direct2D da tale bitmap WIC usando ID2D1DeviceContext::CreateBitmapFromWicBitmap e infine passare direttamente la bitmap Direct2D al controllo di stampa Direct2D senza ulteriori manipolazioni. A tale scopo, il controllo di stampa Direct2D è in grado di riutilizzare il flusso bitmap, che in genere porta a prestazioni di stampa migliori (ignorando la codifica bitmap ridondante e decodifica) e una migliore qualità di stampa (quando i metadati, ad esempio i profili di colore, nella bitmap verranno mantenuti).

Il disegno della bitmap originale offre il vantaggio seguente per le applicazioni.

  • In generale, la stampa Direct2D mantiene le informazioni originali (senza perdita o rumore) fino a tardi nella pipeline, soprattutto quando le app non sanno (o non vogliono sapere) i dettagli della pipeline di stampa (come la stampante a cui sta stampando, a che DPI è la stampante di destinazione e così via).
  • In molti casi, il ritardo della rasterizzazione bitmap significa prestazioni migliori (ad esempio quando si stampa una foto da 96dpi a una stampante a 600dpi).
  • In alcuni casi, il passaggio delle immagini originali è l'unico modo per rispettare l'alta fedeltà (come i profili di colore incorporati).

Tuttavia, un utente non può acconsentire esplicitamente a tale ottimizzazione perché:

  • Eseguendo query sulle informazioni sulla stampante e sulla rasterizzazione anticipata, è possibile rasterizzare il contenuto stesso con il controllo completo dell'aspetto finale sulla carta.
  • In alcuni casi, la rasterizzazione anticipata potrebbe effettivamente migliorare le prestazioni end-to-end di un'app ,ad esempio la stampa di foto con dimensioni dei portafogli.
  • In alcuni casi, il passaggio delle bitmap originali richiede una modifica significativa dell'architettura di codice esistente,ad esempio i percorsi di caricamento e aggiornamento delle risorse rilevati in determinate applicazioni.

Conclusione

Anche se Direct2D è accelerato dall'hardware ed è destinato a prestazioni elevate, è necessario usare correttamente le funzionalità per ottimizzare la velocità effettiva. Le tecniche esaminate sono derivate dallo studio di scenari comuni e potrebbero non essere applicabili a tutti gli scenari dell'applicazione.