Amélioration des performances des applications Direct2D
Bien que Direct2D soit accéléré sur le matériel et qu’il soit conçu pour des performances élevées, vous devez utiliser les fonctionnalités correctement pour optimiser le débit. Les techniques que nous présentons ici sont dérivées de l’étude de scénarios courants et peuvent ne pas s’appliquer à tous les scénarios d’application. Par conséquent, une bonne compréhension du comportement et des objectifs de performances des applications peut vous aider à obtenir les résultats souhaités.
- Utilisation des ressources
- Restreindre l’utilisation du vidage
- Images bitmap
- Utiliser une image bitmap en mosaïque au-dessus du tiret
- Instructions générales pour le rendu du contenu statique complexe
- Mise en cache par primitive à l’aide de réalisations géométriques
- Rendu géométrique
- Dessin de texte avec Direct2D
- Découpage d’une forme arbitraire
- Interopérabilité DXGI : éviter les commutateurs fréquents
- Connaître le format de votre pixel
- Complexité des scènes
- Amélioration des performances des applications d’impression Direct2D
- Conclusion
Utilisation des ressources
Une ressource est une allocation d’une sorte quelconque, que ce soit en mémoire vidéo ou système. Les bitmaps et les pinceaux sont des exemples de ressources.
Dans Direct2D, les ressources peuvent être créées à la fois dans les logiciels et le matériel. La création et la suppression de ressources sur le matériel sont des opérations coûteuses, car elles nécessitent beaucoup de surcharge pour communiquer avec le carte vidéo. Voyons comment Direct2D restitue le contenu vers une cible.
Dans Direct2D, toutes les commandes de rendu sont placées entre un appel à BeginDraw et un appel à EndDraw. Ces appels sont effectués à une cible de rendu. Vous devez appeler la méthode BeginDraw avant d’appeler les opérations de rendu . Après avoir appelé BeginDraw , un contexte génère généralement un lot de commandes de rendu, mais retarde le traitement de ces commandes jusqu’à ce qu’une de ces instructions soit vraie :
- EndDraw s’est produit. Quand EndDraw est appelé, toutes les opérations de dessin par lots se terminent et retourne le status de l’opération.
- Vous effectuez un appel explicite à Flush : la méthode Flush entraîne le traitement du lot et l’émission de toutes les commandes en attente.
- La mémoire tampon contenant les commandes de rendu est pleine. Si cette mémoire tampon devient pleine avant que les deux conditions précédentes ne soient remplies, les commandes de rendu sont vidées.
Jusqu’à ce que les primitives soient vidées, Direct2D conserve les références internes aux ressources correspondantes, telles que les bitmaps et les pinceaux.
Réutiliser des ressources
Comme mentionné précédemment, la création et la suppression de ressources sont coûteuses sur le matériel. Réutilisez donc les ressources dans la mesure du possible. Prenons l’exemple de la création de bitmaps dans le développement de jeux. En règle générale, les bitmaps qui composent une scène dans un jeu sont toutes créées en même temps avec toutes les différentes variantes requises pour le rendu d’image à image ultérieur. Au moment du rendu et du rendu réels de la scène, ces bitmaps sont réutilisées au lieu d’être recréées.
Notes
Vous ne pouvez pas réutiliser les ressources pour l’opération de redimensionnement de fenêtre. Lorsqu’une fenêtre est redimensionnée, certaines ressources dépendantes de l’échelle, telles que les cibles de rendu compatibles et éventuellement certaines ressources de couche, doivent être recréées, car le contenu de la fenêtre doit être redessiné. Cela peut être important pour maintenir la qualité globale de la scène rendue.
Restreindre l’utilisation du vidage
Étant donné que la méthode Flush entraîne le traitement des commandes de rendu par lots, nous vous recommandons de ne pas l’utiliser. Pour les scénarios les plus courants, laissez la gestion des ressources à Direct2D.
Images bitmap
Comme mentionné précédemment, la création et la suppression de ressources sont des opérations très coûteuses dans le matériel. Une bitmap est un type de ressource qui est souvent utilisé. La création de bitmaps sur le carte vidéo est coûteuse. Leur réutilisation peut aider à accélérer l’application.
Créer de grandes bitmaps
Les cartes vidéo ont généralement une taille minimale d’allocation de mémoire. Si une allocation plus petite que celle-ci est demandée, une ressource de cette taille minimale est allouée et la mémoire excédentaire est gaspide et indisponible pour d’autres éléments. Si vous avez besoin de nombreuses petites bitmaps, une meilleure technique consiste à allouer une grande bitmap et à stocker tout le contenu de la petite bitmap dans cette grande bitmap. Ensuite, les sous-zones de l’image bitmap plus grande peuvent être lues là où les images bitmap plus petites sont nécessaires. Souvent, vous devez inclure le remplissage (pixels noirs transparents) entre les petites bitmaps pour éviter toute interaction entre les images plus petites pendant les opérations. Il s’agit également d’un atlas, qui présente l’avantage de réduire la surcharge de création de bitmaps et le gaspillage de mémoire des allocations de bitmap de petite taille. Nous vous recommandons de conserver la plupart des bitmaps à au moins 64 Ko et de limiter le nombre de bitmaps inférieures à 4 Ko.
Créer un atlas de bitmaps
Il existe certains scénarios courants pour lesquels un atlas bitmap peut très bien servir. Les petites bitmaps peuvent être stockées à l’intérieur d’une grande bitmap. Ces petites bitmaps peuvent être extraites de la plus grande bitmap lorsque vous en avez besoin en spécifiant le rectangle de destination. Par exemple, une application doit dessiner plusieurs icônes. Toutes les bitmaps associées aux icônes peuvent être chargées dans une grande bitmap à l’avance. Et au moment du rendu, ils peuvent être récupérés à partir de la grande bitmap.
Notes
Une bitmap Direct2D créée dans la mémoire vidéo est limitée à la taille maximale de bitmap prise en charge par l’adaptateur sur lequel elle est stockée. La création d’une bitmap supérieure à peut entraîner une erreur.
Notes
À compter de Windows 8, Direct2D inclut un effet Atlas qui peut faciliter ce processus.
Créer des bitmaps partagées
La création de bitmaps partagées permet aux appelants avancés de créer des objets bitmap Direct2D qui sont sauvegardés directement par un objet existant, déjà compatible avec la cible de rendu. Cela évite de créer plusieurs surfaces et permet de réduire la surcharge des performances.
Notes
Les bitmaps partagées sont généralement limitées aux cibles logicielles ou aux cibles interopérables avec DXGI. Utilisez les méthodes CreateBitmapFromDxgiSurface, CreateBitmapFromWicBitmap et CreateSharedBitmap pour créer des bitmaps partagées.
Copie de bitmaps
La création d’une surface DXGI est une opération coûteuse, donc réutilisez les surfaces existantes quand vous le pouvez. Même dans les logiciels, si une bitmap est principalement dans la forme souhaitée, à l’exception d’une petite partie, il est préférable de mettre à jour cette partie plutôt que de jeter l’intégralité de la bitmap et de tout recréer. Bien que vous puissiez utiliser CreateCompatibleRenderTarget pour obtenir les mêmes résultats, le rendu est généralement une opération beaucoup plus coûteuse que la copie. Cela est dû au fait que, pour améliorer la localité du cache, le matériel ne stocke pas réellement une bitmap dans le même ordre de mémoire que celui auquel la bitmap est traitée. Au lieu de cela, la bitmap peut être swizzled. Le swizzling est masqué du processeur soit par le pilote (qui est lent et utilisé uniquement sur les parties inférieures), soit par le gestionnaire de mémoire sur le GPU. En raison de contraintes sur la façon dont les données sont écrites dans une cible de rendu lors du rendu, les cibles de rendu ne sont généralement pas swizzled, ou swizzled d’une manière moins optimale que peut être obtenue si vous savez que vous n’avez jamais à effectuer de rendu à la surface. Par conséquent, les méthodes CopyFrom* sont fournies pour copier des rectangles d’une source vers la bitmap Direct2D.
CopyFrom peut être utilisé sous l’une de ses trois formes :
Utiliser une bitmap en mosaïque sur des tirets
Le rendu d’une ligne en pointillés est une opération très coûteuse en raison de la haute qualité et de la précision de l’algorithme sous-jacent. Dans la plupart des cas qui n’impliquent pas de géométries rectilignes, le même effet peut être généré plus rapidement à l’aide de bitmaps en mosaïques.
Instructions générales pour le rendu du contenu statique complexe
Mettez en cache le contenu si vous affichez le même cadre de contenu sur image, en particulier lorsque la scène est complexe.
Il existe trois techniques de mise en cache que vous pouvez utiliser :
- Mise en cache de scène complète à l’aide d’une bitmap de couleur.
- Par mise en cache primitive à l’aide d’une bitmap A8 et de la méthode FillOpacityMask .
- Mise en cache par primitive à l’aide de réalisations géométriques.
Examinons chacun de ces éléments plus en détail.
Mise en cache de scène complète à l’aide d’une bitmap de couleur
Lorsque vous affichez du contenu statique, dans des scénarios tels que l’animation, créez une autre image bitmap en couleur au lieu d’écrire directement dans la bitmap d’écran. Enregistrez la cible actuelle, définissez la cible sur l’image bitmap intermédiaire et restituez le contenu statique. Ensuite, revenez à la bitmap d’écran d’origine et dessinez la bitmap intermédiaire dessus.
Voici un exemple :
// 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());
Cet exemple utilise des bitmaps intermédiaires pour la mise en cache et bascule la bitmap vers laquelle pointe le contexte de l’appareil lors du rendu. Cela évite d’avoir à créer une cible de rendu compatible dans le même but.
Mise en cache par primitive à l’aide d’une bitmap A8 et de la méthode FillOpacityMask
Lorsque la scène complète n’est pas statique, mais se compose d’éléments tels que la géométrie ou le texte qui sont statiques, vous pouvez utiliser une technique de mise en cache par primitive. Cette technique conserve les caractéristiques d’anticrénelage de la primitive mise en cache et fonctionne avec les types de pinceaux changeants. Il utilise une bitmap A8 où A8 est une sorte de format de pixel qui représente un canal alpha avec 8 bits. Les bitmaps A8 sont utiles pour dessiner une géométrie/du texte sous forme de masque. Lorsque vous devez manipuler l’opacité du contenu statique , au lieu de manipuler le contenu lui-même, vous pouvez traduire, faire pivoter, biaiser ou mettre à l’échelle l’opacité du masque.
Voici un exemple :
// 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);
Mise en cache par primitive à l’aide de réalisations géométriques
Une autre technique de mise en cache par primitive, appelée réalisation de géométrie, offre une plus grande flexibilité lors de la gestion de la géométrie. Lorsque vous souhaitez dessiner à plusieurs reprises des géométries alias ou anticrénelées, il est plus rapide de les convertir en réalisations géométriques et de dessiner à plusieurs reprises les réalisations que de dessiner les géométries elles-mêmes à plusieurs reprises. Les réalisations géométriques consomment généralement moins de mémoire que les masques d’opacité (en particulier pour les géométries volumineuses), et elles sont moins sensibles aux changements d’échelle. Pour plus d’informations, consultez Vue d’ensemble des réalisations géométriques.
Voici un exemple :
// 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();
Rendu de la géométrie
Utiliser une primitive de dessin spécifique sur une géométrie de dessin
Utilisez des appelsde primitives de dessin plus spécifiques, comme DrawRectangle , sur des appels DrawGeometry génériques. En effet, avec DrawRectangle, la géométrie est déjà connue et le rendu est donc plus rapide.
Rendu de la géométrie statique
Dans les scénarios où la géométrie est statique, utilisez les techniques de mise en cache par primitive expliquées ci-dessus. Les masques d’opacité et les réalisations géométriques peuvent considérablement améliorer la vitesse de rendu des scènes qui contiennent de la géométrie statique.
Utiliser un contexte d’appareil multithread
Les applications qui s’attendent à afficher des quantités significatives de contenu géométrique complexe doivent envisager de spécifier l’indicateur D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTI_THREADED_OPTIMIZATIONS lors de la création d’un contexte d’appareil Direct2D . Lorsque cet indicateur est spécifié, Direct2D distribue le rendu sur tous les cœurs logiques présents sur le système, ce qui peut réduire considérablement le temps de rendu global.
Remarques :
- À partir de Windows 8.1, cet indicateur affecte uniquement le rendu de la géométrie du chemin. Il n’a aucun impact sur les scènes contenant uniquement d’autres types primitifs (tels que du texte, des bitmaps ou des réalisations géométriques).
- Cet indicateur n’a pas non plus d’impact lors du rendu dans le logiciel (c’est-à-dire lors du rendu avec un appareil WARP Direct3D). Pour contrôler le multithreading logiciel, les appelants doivent utiliser l’indicateur D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS lors de la création de l’appareil WARP Direct3D.
- La spécification de cet indicateur peut augmenter les pics de travail pendant le rendu et peut également augmenter la contention de threads dans les applications qui tirent déjà parti du traitement multithread.
Dessin de texte avec Direct2D
La fonctionnalité de rendu de texte Direct2D est proposée en deux parties. La première partie, exposée en tant que méthode ID2D1RenderTarget::D rawText et ID2D1RenderTarget::D rawTextLayout , permet à un appelant de passer une chaîne et des paramètres de mise en forme ou un objet de disposition de texte DWrite pour plusieurs formats. Cela devrait convenir à la plupart des appelants. La deuxième méthode de rendu du texte, exposée en tant que méthode ID2D1RenderTarget::D rawGlyphRun , fournit une rastérisation pour les clients qui connaissent déjà la position des glyphes qu’ils souhaitent afficher. Les deux règles générales suivantes peuvent aider à améliorer les performances du texte lors du dessin dans Direct2D.
DrawTextLayout et DrawText
DrawText et DrawTextLayout permettent à une application de rendre facilement du texte mis en forme par l’API DirectWrite. DrawTextLayout dessine un objet DWriteTextLayout existant dans renderTarget, et DrawText construit une disposition DirectWrite pour l’appelant, en fonction des paramètres passés. Si le même texte doit être rendu plusieurs fois, utilisez DrawTextLayout au lieu de DrawText, car DrawText crée une disposition chaque fois qu’elle est appelée.
Choix du mode de rendu de texte approprié
Définissez le mode anticrénel texte sur D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE explicitement. La qualité du rendu du texte en nuances de gris est comparable à ClearType, mais elle est beaucoup plus rapide.
Mise en cache
Utilisez la mise en cache de scène complète ou par bitmap primitive, comme avec le dessin d’autres primitives.
Découpage d’une forme arbitraire
La figure montre ici le résultat de l’application d’un clip à une image.
Vous pouvez obtenir ce résultat à l’aide de couches avec un masque de géométrie ou de la méthode FillGeometry avec un pinceau d’opacité.
Voici un exemple qui utilise une couche :
// Call PushLayer() and pass in the clipping geometry.
m_d2dContext->PushLayer(
D2D1::LayerParameters(
boundsRect,
geometricMask));
Voici un exemple qui utilise la méthode 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());
Dans cet exemple de code, lorsque vous appelez la méthode PushLayer, vous ne passez pas une couche créée par l’application. Direct2D crée une couche pour vous. Direct2D est en mesure de gérer l’allocation et la destruction de cette ressource sans aucune intervention de l’application. Cela permet à Direct2D de réutiliser les couches en interne et d’appliquer des optimisations de gestion des ressources.
Dans Windows 8 de nombreuses optimisations ont été apportées à l’utilisation des couches et nous vous recommandons d’essayer d’utiliser des API de couche au lieu de FillGeometry dans la mesure du possible.
PushLayer dans Windows 8
L’interface ID2D1DeviceContext est dérivée de l’interface ID2D1RenderTarget et est essentielle pour afficher le contenu Direct2D dans Windows 8. Pour plus d’informations sur cette interface, consultez Appareils et contextes d’appareil. Avec l’interface de contexte de l’appareil, vous pouvez ignorer l’appel de la méthode CreateLayer , puis passer la valeur NULL à la méthode ID2D1DeviceContext::P ushLayer . Direct2D gère automatiquement la ressource de couche et peut partager des ressources entre les couches et les graphiques d’effet.
Clips alignés sur l’axe
Si la région à couper est alignée sur l’axe de la surface de dessin, au lieu d’arbitraire. Ce cas est adapté à l’utilisation d’un rectangle de clip au lieu d’une couche. Le gain de performances est plus pour la géométrie avec alias que pour la géométrie antialiased. Pour plus d’informations sur les clips alignés sur l’axe, consultez la rubrique PushAxisAlignedClip .
Interopérabilité DXGI : éviter les commutateurs fréquents
Direct2D peut interagir en toute transparence avec les surfaces Direct3D. Cela est très utile pour créer des applications qui affichent un mélange de contenu 2D et 3D. Toutefois, chaque basculement entre le dessin du contenu Direct2D et Direct3D affecte les performances.
Lors du rendu sur une surface DXGI, Direct2D enregistre l’état des appareils Direct3D lors du rendu et le restaure une fois le rendu terminé. Chaque fois qu’un lot de rendu Direct2D est terminé, le coût de cette économie et de cette restauration et le coût du vidage de toutes les opérations 2D sont payés, et pourtant, l’appareil Direct3D n’est pas vidé. Par conséquent, pour augmenter les performances, limitez le nombre de commutateurs de rendu entre Direct2D et Direct3D.
Connaître le format de votre pixel
Lorsque vous créez une cible de rendu, vous pouvez utiliser la structure D2D1_PIXEL_FORMAT spécifier le format de pixel et le mode alpha utilisés par la cible de rendu. Un canal alpha fait partie du format de pixels qui spécifie la valeur de couverture ou les informations d’opacité. Si une cible de rendu n’utilise pas le canal alpha, elle doit être créée à l’aide du mode alpha D2D1_ALPHA_MODE_IGNORE . Cela permet de ménager le temps consacré au rendu d’un canal alpha qui n’est pas nécessaire.
Pour plus d’informations sur les formats de pixels et les modes alpha, consultez Formats de pixels et modes alpha pris en charge.
Complexité des scènes
Lorsque vous analysez les points chauds des performances dans une scène qui sera rendue, savoir si la scène est liée au taux de remplissage ou au vertex peut fournir des informations utiles.
- Taux de remplissage : le taux de remplissage fait référence au nombre de pixels qu’un graphique carte peut afficher et écrire dans la mémoire vidéo par seconde.
- Vertex Bound : une scène est liée au vertex lorsqu’elle contient beaucoup de géométrie complexe.
Comprendre la complexité des scènes
Vous pouvez analyser la complexité de votre scène en modifiant la taille de la cible de rendu. Si des gains de performances sont visibles pour une réduction proportionnelle de la taille de la cible de rendu, l’application est liée au taux de remplissage. Sinon, la complexité de la scène est le goulot d’étranglement des performances.
Lorsqu’une scène est liée au taux de remplissage, la réduction de la taille de la cible de rendu peut améliorer les performances. Cela est dû au fait que le nombre de pixels à afficher sera réduit proportionnellement à la taille de la cible de rendu.
Lorsqu’une scène est liée au vertex, réduisez la complexité de la géométrie. Mais rappelez-vous que cela se fait au détriment de la qualité de l’image. Par conséquent, une décision soigneuse doit être prise entre la qualité souhaitée et le rendement requis.
Amélioration des performances des applications d’impression Direct2D
Direct2D offre une compatibilité avec l’impression. Vous pouvez envoyer les mêmes commandes de dessin Direct2D (sous la forme de listes de commandes Direct2D) au contrôle d’impression Direct2D pour l’impression, si vous ne savez pas vers quels appareils vous dessinez ou comment le dessin est traduit en impression.
Vous pouvez affiner davantage leur utilisation du contrôle d’impression Direct2D et de vos commandes de dessin Direct2D pour fournir des résultats d’impression avec de meilleures performances.
Le contrôle d’impression Direct2D génère des messages de débogage lorsqu’il voit un modèle de code Direct2D qui entraîne une qualité d’impression ou des performances inférieures (comme les modèles de code répertoriés plus loin dans cette rubrique) pour vous rappeler où vous pouvez éviter les problèmes de performances. Pour afficher ces messages de débogage, vous devez activer la couche de débogage Direct2D dans votre code. Consultez Messages de débogage pour obtenir des instructions sur l’activation de la sortie des messages de débogage.
Définir les valeurs de propriété appropriées lorsque vous créez le contrôle d’impression D2D
Vous pouvez définir trois propriétés lorsque vous créez le contrôle d’impression Direct2D . Deux de ces propriétés ont un impact sur la façon dont le contrôle d’impression Direct2D gère certaines commandes Direct2D et ont à leur tour un impact sur les performances globales.
- Mode de sous-ensemble de polices : le contrôle d’impression Direct2D sous-ensembles sous-ensembles des ressources de police utilisées dans chaque page avant d’envoyer la page à imprimer. Ce mode réduit la taille des ressources de page nécessaires à l’impression. En fonction de l’utilisation de la police sur la page, vous pouvez choisir différents modes de sous-ensemble de polices pour obtenir les meilleures performances.
- D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT offre les meilleures performances d’impression dans la plupart des cas. Lorsqu’il est défini sur ce mode, le contrôle d’impression Direct2D utilise une stratégie heuristique pour décider quand créer un sous-ensemble de polices.
- Pour les travaux d’impression courte de 1 ou 2 pages, nous vous recommandons d’D2D1_PRINT_FONT_SUBSET_MODE_EACHPAGE , où le contrôle d’impression Direct2D sous-ensembles et incorpore des ressources de police dans chaque page, puis ignore ce sous-ensemble de polices après l’impression de la page. Cette option permet de s’assurer que chaque page peut être imprimée immédiatement après sa génération, mais augmente légèrement la taille des ressources de page nécessaires pour l’impression (avec généralement des sous-ensembles de polices volumineux).
- Pour les travaux d’impression avec de nombreuses pages de texte et de petites tailles de police (comme 100 pages de texte qui utilise une police unique), nous vous recommandons de D2D1_PRINT_FONT_SUBSET_MODE_NONE, où le contrôle d’impression Direct2D ne sous-traite pas du tout les ressources de police ; au lieu de cela, il envoie les ressources de police d’origine ainsi que la page qui utilise d’abord la police, et ré-utilise les ressources de police pour les pages ultérieures sans les renvoyer.
- Ppp de rastérisation : lorsque le contrôle d’impression Direct2D doit rastériser les commandes Direct2D pendant la conversion Direct2D-XPS, il utilise ce DPI pour la rastérisation. En d’autres termes, si la page n’a pas de contenu rastérisé, la définition d’un ppp ne modifie pas les performances et la qualité. En fonction de l’utilisation de la rastérisation sur la page, vous pouvez choisir différents DPI de rastérisation pour le meilleur équilibre entre fidélité et performances.
- 150 est la valeur par défaut si vous ne spécifiez pas de valeur lorsque vous créez le contrôle d’impression Direct2D , qui est le meilleur équilibre entre la qualité d’impression et les performances d’impression dans la plupart des cas.
- Les valeurs DPI plus élevées entraînent généralement une meilleure qualité d’impression (comme dans d’autres détails conservés), mais des performances inférieures en raison des bitmaps plus volumineuses qu’elles génèrent. Nous ne recommandons aucune valeur DPI supérieure à 300, car cela n’introduit pas d’informations supplémentaires visuellement perceptibles par les yeux humains.
- Un DPI plus faible peut signifier de meilleures performances, mais peut également produire une qualité inférieure.
Évitez d’utiliser certains modèles de dessin Direct2D
Il existe des différences entre ce que Direct2D peut représenter visuellement et ce que le sous-système d’impression peut gérer et transporter tout au long du pipeline d’impression. Le contrôle d’impression Direct2D comble ces lacunes en approchant ou en rastérisant les primitives Direct2D que le sous-système d’impression ne prend pas en charge en mode natif. Cette approximation se traduit généralement par une fidélité d’impression inférieure, des performances d’impression inférieures ou les deux. Par conséquent, même si un client peut utiliser les mêmes motifs de dessin pour le rendu d’écran et d’impression, ce n’est pas idéal dans tous les cas. Il est préférable de ne pas utiliser autant que possible ces primitives et modèles Direct2D pour le chemin d’impression, ou d’effectuer votre propre rastérisation où vous avez le contrôle total de la qualité et de la taille des images rastérisées.
Voici une liste de cas où les performances et la qualité d’impression ne sont pas idéales et que vous pouvez envisager de faire varier le chemin du code pour optimiser les performances d’impression.
- Évitez d’utiliser le mode de fusion primitif autre que D2D1_PRIMITIVE_BLEND_SOURCEOVER.
- Évitez d’utiliser les modes composition lors du dessin d’une image autre que D2D1_COMPOSITE_MODE_SOURCE_OVER et D2D1_COMPOSITE_MODE_DESTINATION_OVER.
- Évitez de dessiner un meta file GDI.
- Évitez d’envoyer (push) une ressource de couche qui copie l’arrière-plan source (en appelant PushLayer en passant des D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND au D2D1_LAYER_PARAMETERS1 struct).
- Évitez de créer un pinceau bitmap ou un pinceau d’image avec D2D1_EXTEND_MODE_CLAMP. Nous vous recommandons d’utiliser D2D1_EXTEND_MODE_MIRROR si vous ne vous souciez pas du tout des pixels en dehors de l’image liée (par exemple, l’image attachée au pinceau est connue pour être plus grande que la région cible remplie).
- Évitez de dessiner des bitmaps avec des transformations de perspective.
Dessiner du texte de manière directe et simple
Direct2D a plusieurs optimisations lors du rendu des textes à afficher pour de meilleures performances et/ou une meilleure qualité visuelle. Mais toutes les optimisations n’améliorent pas les performances et la qualité de l’impression, car l’impression sur papier est généralement dans un DPI beaucoup plus élevé, et l’impression n’a pas besoin de prendre en charge des scénarios tels que l’animation. Par conséquent, nous vous recommandons de dessiner directement le texte ou les glyphes d’origine et d’éviter les optimisations suivantes lors de la création de la liste de commandes pour l’impression.
- Évitez de dessiner du texte avec la méthode FillOpacityMask .
- Évitez de dessiner du texte en mode alias.
Dessinez les bitmaps d’origine lorsque cela est possible
Si l’image bitmap cible est un bitmap JPEG, PNG, TIFF ou JPEG-XR, vous pouvez créer une bitmap WIC à partir d’un fichier disque ou d’un flux en mémoire, puis créer une bitmap Direct2D à partir de cette bitmap WIC à l’aide de ID2D1DeviceContext::CreateBitmapFromWicBitmap, et enfin passer directement cette bitmap Direct2D au contrôle d’impression Direct2D sans autre manipulation. Ce faisant, le contrôle d’impression Direct2D est en mesure de réutiliser le flux bitmap, ce qui entraîne généralement de meilleures performances d’impression (en ignorant l’encodage et le décodage redondants de bitmap) et une meilleure qualité d’impression (lorsque les métadonnées, telles que les profils de couleur, dans la bitmap seront conservées).
Le dessin de la bitmap d’origine offre l’avantage suivant pour les applications.
- En général, l’impression Direct2D conserve les informations d’origine (sans perte ni bruit) jusqu’à la fin du pipeline, en particulier lorsque les applications ne connaissent pas (ou ne veulent pas connaître) les détails du pipeline d’impression (comme l’imprimante sur laquelle elle imprime, quel ppp est l’imprimante cible, etc.).
- Dans de nombreux cas, retarder la rastérisation bitmap signifie de meilleures performances (comme lors de l’impression d’une photo de 96 ppp sur une imprimante de 600 ppp).
- Dans certains cas, la transmission des images d’origine est la seule façon d’honorer la haute fidélité (comme les profils de couleurs incorporés).
Toutefois, vous ne pouvez pas opter pour une telle optimisation pour les raisons suivantes :
- En interrogeant les informations d’imprimante et la rastérisation précoce, vous pouvez rasteriser le contenu lui-même avec un contrôle total sur l’apparence finale sur papier.
- Dans certains cas, la rastérisation précoce peut en fait améliorer les performances d’une application de bout en bout (comme l’impression de photos au format portefeuille).
- Dans certains cas, le passage des bitmaps d’origine nécessite un changement important de l’architecture de code existante (comme le chargement différé de l’image et les chemins de mise à jour des ressources trouvés dans certaines applications).
Conclusion
Bien que Direct2D soit accéléré sur le matériel et qu’il soit conçu pour des performances élevées, vous devez utiliser les fonctionnalités correctement pour optimiser le débit. Les techniques que nous avons examinées ici sont dérivées de l’étude de scénarios courants et peuvent ne pas s’appliquer à tous les scénarios d’application.