Share via


Mejora del rendimiento de las aplicaciones de Direct2D

Aunque Direct2D está acelerado por hardware y está pensado para un alto rendimiento, debe usar las características correctamente para maximizar el rendimiento. Las técnicas que se muestran aquí se derivan del estudio de escenarios comunes y es posible que no se apliquen a todos los escenarios de la aplicación. Por lo tanto, comprender detenidamente el comportamiento de la aplicación y los objetivos de rendimiento pueden ayudar a lograr los resultados que desee.

Uso de recursos

Un recurso es una asignación de algún tipo, ya sea en la memoria de vídeo o del sistema. Los mapas de bits y pinceles son ejemplos de recursos.

En Direct2D, los recursos se pueden crear tanto en software como en hardware. La creación y eliminación de recursos en hardware son operaciones costosas porque requieren mucha sobrecarga para comunicarse con la tarjeta de vídeo. Veamos cómo Direct2D representa el contenido en un destino.

En Direct2D, todos los comandos de representación se incluyen entre una llamada a BeginDraw y una llamada a EndDraw. Estas llamadas se realizan en un destino de representación. Debe llamar al método BeginDraw antes de llamar a las operaciones de representación . Después de llamar a BeginDraw , un contexto normalmente crea un lote de comandos de representación, pero retrasa el procesamiento de estos comandos hasta que se cumple una de estas instrucciones:

  • EndDraw se produjo. Cuando se llama a EndDraw , hace que las operaciones de dibujo por lotes se completen y devuelvan el estado de la operación.
  • Realice una llamada explícita a Flush: el método Flush hace que se procese el lote y se emita todos los comandos pendientes.
  • El búfer que contiene los comandos de representación está lleno. Si este búfer se llena antes de que se cumplan las dos condiciones anteriores, los comandos de representación se vacían.

Hasta que se vacían los primitivos, Direct2D mantiene las referencias internas a los recursos correspondientes, como mapas de bits y pinceles.

Reutilización de recursos

Como ya se mencionó, la creación y eliminación de recursos es costosa en el hardware. Por lo tanto, vuelva a usar los recursos siempre que sea posible. Tome el ejemplo de creación de mapas de bits en el desarrollo de juegos. Normalmente, los mapas de bits que componen una escena en un juego se crean al mismo tiempo con todas las diferentes variaciones necesarias para la representación posterior de fotograma a fotograma. En el momento de la representación real de la escena y la nueva representación, estos mapas de bits se reutilizan en lugar de volver a crearse.

Nota

No se pueden reutilizar los recursos para la operación de cambio de tamaño de la ventana. Cuando se cambia el tamaño de una ventana, algunos recursos dependientes de la escala, como destinos de representación compatibles y, posiblemente, se deben volver a crear algunos recursos de capa porque el contenido de la ventana debe volver a dibujarse. Esto puede ser importante para mantener la calidad general de la escena representada.

 

Restringir el uso de vaciado

Dado que el método Flush hace que se procesen los comandos de representación por lotes, se recomienda no usarlo. Para los escenarios más comunes, deje la administración de recursos en Direct2D.

Mapas de bits

Como se mencionó anteriormente, la creación y eliminación de recursos son operaciones muy costosas en hardware. Un mapa de bits es un tipo de recurso que se usa a menudo. La creación de mapas de bits en la tarjeta de vídeo es costosa. Reutilizarlas puede ayudar a que la aplicación sea más rápida.

Creación de mapas de bits grandes

Las tarjetas de vídeo suelen tener un tamaño mínimo de asignación de memoria. Si se solicita una asignación menor que esta, se asigna un recurso de este tamaño mínimo y se desperdicia la memoria sobrante y no está disponible para otras cosas. Si necesita muchos mapas de bits pequeños, una mejor técnica consiste en asignar un mapa de bits grande y almacenar todo el contenido del mapa de bits pequeño en este mapa de bits grande. A continuación, se pueden leer subáreas del mapa de bits más grande donde se necesitan los mapas de bits más pequeños. A menudo, debe incluir relleno (píxeles negros transparentes) entre los pequeños mapas de bits para evitar cualquier interacción entre las imágenes más pequeñas durante las operaciones. Esto también se conoce como atlas, y tiene la ventaja de reducir la sobrecarga de creación de mapas de bits y el desperdicio de memoria de asignaciones de mapas de bits pequeños. Se recomienda mantener la mayoría de los mapas de bits en al menos 64 KB y limitar el número de mapas de bits menores que 4 KB.

Creación de un atlas de mapas de bits

Hay algunos escenarios comunes para los que un atlas de mapa de bits puede servir muy bien. Los mapas de bits pequeños se pueden almacenar dentro de un mapa de bits grande. Estos pequeños mapas de bits se pueden extraer del mapa de bits más grande cuando los necesite especificando el rectángulo de destino. Por ejemplo, una aplicación tiene que dibujar varios iconos. Todos los mapas de bits asociados a los iconos se pueden cargar en un mapa de bits grande por adelantado. Y en tiempo de representación, se pueden recuperar del mapa de bits grande.

Nota

Un mapa de bits de Direct2D creado en memoria de vídeo se limita al tamaño máximo de mapa de bits admitido por el adaptador en el que se almacena. La creación de un mapa de bits mayor de lo que podría dar lugar a un error.

 

Nota

A partir de Windows 8, Direct2D incluye un efecto Atlas que puede facilitar este proceso.

 

Creación de mapas de bits compartidos

La creación de mapas de bits compartidos permite a los llamadores avanzados crear objetos de mapa de bits direct2D respaldados directamente por un objeto existente, ya compatibles con el destino de representación. Esto evita la creación de varias superficies y ayuda a reducir la sobrecarga de rendimiento.

Nota

Los mapas de bits compartidos suelen limitarse a los destinos de software o a los destinos interoperables con DXGI. Use los métodos CreateBitmapFromDxgiSurface, CreateBitmapFromWicBitmap y CreateSharedBitmap para crear mapas de bits compartidos.

 

Copiar mapas de bits

La creación de una superficie DXGI es una operación costosa, por lo que se reutilizan las superficies existentes cuando se puede. Incluso en el software, si un mapa de bits está principalmente en el formato que desea excepto para una pequeña parte, es mejor actualizar esa parte que lanzar todo el mapa de bits y volver a crear todo. Aunque puede usar CreateCompatibleRenderTarget para lograr los mismos resultados, la representación suele ser una operación mucho más costosa que copiar. Esto se debe a que, para mejorar la localidad de caché, el hardware no almacena realmente un mapa de bits en el mismo orden de memoria al que se dirige el mapa de bits. En su lugar, es posible que el mapa de bits se desconcerte. El desenlazado está oculto de la CPU por el controlador (que es lento y solo se usa en partes de extremo inferior) o por el administrador de memoria en la GPU. Debido a las restricciones sobre cómo se escriben los datos en un destino de representación cuando se representa, los destinos de representación normalmente no se deslumbran o se deslumbran de una manera que sea menos óptima de la que se puede lograr si sabe que nunca tiene que representarse en la superficie. Por lo tanto, los métodos CopyFrom* se proporcionan para copiar rectángulos desde un origen al mapa de bits de Direct2D.

CopyFrom se puede usar en cualquiera de sus tres formas:

Uso del mapa de bits en mosaico sobre guiones

La representación de una línea discontinua es una operación muy costosa debido a la alta calidad y precisión del algoritmo subyacente. Para la mayoría de los casos que no implican geometrías rectilíneas, el mismo efecto se puede generar más rápido mediante mapas de bits en mosaico.

Directrices generales para representar contenido estático complejo

Almacenar en caché el contenido si representa el mismo marco de contenido sobre fotogramas, especialmente cuando la escena es compleja.

Hay tres técnicas de almacenamiento en caché que puede usar:

  • Almacenamiento en caché de escena completa mediante un mapa de bits de color.
  • Por almacenamiento en caché primitivo mediante un mapa de bits A8 y el método FillOpacityMask .
  • Almacenamiento en caché por primitivo mediante realizaciones de geometría.

Echemos un vistazo a cada uno de ellos con más detalle.

Almacenamiento en caché de escena completa mediante un mapa de bits de color

Al representar contenido estático, en escenarios como la animación, cree otro mapa de bits de color completo en lugar de escribir directamente en el mapa de bits de pantalla. Guarde el destino actual, establezca el destino en el mapa de bits intermedio y represente el contenido estático. A continuación, vuelva al mapa de bits de pantalla original y dibuje el mapa de bits intermedio en él.

Este es un ejemplo:

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

En este ejemplo se usan mapas de bits intermedios para el almacenamiento en caché y se cambia el mapa de bits al que apunta el contexto del dispositivo cuando se representa. Esto evita la necesidad de crear un destino de representación compatible con el mismo propósito.

Almacenamiento en caché por primitivo mediante un mapa de bits A8 y el método FillOpacityMask

Cuando la escena completa no es estática, pero consta de elementos como geometría o texto estáticos, puede usar una técnica de almacenamiento en caché primitiva. Esta técnica conserva las características de suavizado de contorno del primitivo que se almacena en caché y funciona con el cambio de tipos de pincel. Usa un mapa de bits A8 donde A8 es un tipo de formato de píxel que representa un canal alfa con 8 bits. Los mapas de bits A8 son útiles para dibujar geometría o texto como máscara. Cuando debe manipular la opacidad del contenido estático, en lugar de manipular el propio contenido, puede traducir, rotar, sesgar o escalar la opacidad de la máscara.

Este es un ejemplo:

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

Almacenamiento en caché por primitivo mediante realizaciones de geometría

Otra técnica de almacenamiento en caché por primitivo, denominada realización de geometría, proporciona mayor flexibilidad al tratar con geometría. Cuando se desea dibujar repetidamente geometrías con alias o anti alias, es más rápido convertirlos en realizaciones de geometría y dibujar repetidamente las realizaciones que para dibujar repetidamente las geometrías en sí mismas. Las realizaciones de geometría también suelen consumir menos memoria que las máscaras de opacidad (especialmente para geometrías grandes) y son menos sensibles a los cambios en la escala. Para obtener más información, consulte Información general sobre las realizaciones de geometría.

Este es un ejemplo:

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

Representación de geometría

Uso de una primitiva de dibujo específica sobre la geometría de dibujo

Use llamadasprimitivas de dibujo más específicas, como DrawRectangle a través de llamadas genéricas a DrawGeometry . Esto se debe a que con DrawRectangle, la geometría ya se conoce, por lo que la representación es más rápida.

Representación de geometría estática

En escenarios en los que la geometría es estática, use las técnicas de almacenamiento en caché por primitivo que se han explicado anteriormente. Las máscaras de opacidad y las realizaciones de geometría pueden mejorar considerablemente la velocidad de representación de las escenas que contienen geometría estática.

Uso de un contexto de dispositivo multiproceso

Las aplicaciones que esperan representar cantidades significativas de contenido geométrico complejo deben considerar la posibilidad de especificar la marca D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTI_THREADED_OPTIMIZATIONS al crear un contexto de dispositivo Direct2D . Cuando se especifica esta marca, Direct2D distribuirá la representación en todos los núcleos lógicos presentes en el sistema, lo que puede reducir significativamente el tiempo total de representación.

Notas:

  • A partir de Windows 8.1, esta marca solo afecta a la representación de geometría de ruta de acceso. No tiene ningún impacto en las escenas que contienen solo otros tipos primitivos (como texto, mapas de bits o realizaciones de geometría).
  • Esta marca tampoco tiene ningún impacto al representar en software (es decir, al representar con un dispositivo WARP Direct3D). Para controlar el multithreading de software, los autores de llamadas deben usar la marca D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS al crear el dispositivo WARP Direct3D.
  • La especificación de esta marca puede aumentar el conjunto de trabajo máximo durante la representación y también puede aumentar la contención de subprocesos en las aplicaciones que ya aprovechan el procesamiento multiproceso.

Dibujo de texto con Direct2D

La funcionalidad de representación de texto direct2D se ofrece en dos partes. La primera parte, expuesta como el método ID2D1RenderTarget::D rawText y ID2D1RenderTarget::D rawTextLayout , permite a un llamador pasar parámetros de formato y cadena o un objeto de diseño de texto DWrite para varios formatos. Esto debe ser adecuado para la mayoría de los autores de llamadas. La segunda forma de representar texto, expuesto como el método ID2D1RenderTarget::D rawGlyphRun , proporciona rasterización para los clientes que ya conocen la posición de los glifos que desean representar. Las dos reglas generales siguientes pueden ayudar a mejorar el rendimiento del texto al dibujar en Direct2D.

DrawTextLayout frente a DrawText

DrawText y DrawTextLayout permiten que una aplicación represente fácilmente texto con el formato de la API de DirectWrite. DrawTextLayout dibuja un objeto DWriteTextLayout existente en RenderTarget y DrawText construye un diseño de DirectWrite para el autor de la llamada, en función de los parámetros que se pasan. Si el mismo texto tiene que representarse varias veces, use DrawTextLayout en lugar de DrawText, ya que DrawText crea un diseño cada vez que se llama a él.

Elección del modo de representación de texto adecuado

Establezca el modo antialias de texto en D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE explícitamente. La calidad del texto de escala de grises de representación es comparable a ClearType, pero es mucho más rápida.

Almacenamiento en memoria caché

Use la escena completa o el almacenamiento en caché por mapa de bits primitivo, como con dibujar otros primitivos.

Recorte de una forma arbitraria

La ilustración aquí muestra el resultado de aplicar un clip a una imagen.

una imagen que muestra un ejemplo de una imagen antes y después de un clip.

Puede obtener este resultado mediante capas con una máscara de geometría o el método FillGeometry con un pincel de opacidad.

Este es un ejemplo que usa una capa:

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

Este es un ejemplo que usa el método 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()); 

En este ejemplo de código, cuando se llama al método PushLayer, no se pasa una capa creada por la aplicación. Direct2D crea una capa automáticamente. Direct2D puede administrar la asignación y destrucción de este recurso sin ninguna intervención de la aplicación. Esto permite a Direct2D reutilizar las capas internamente y aplicar optimizaciones de administración de recursos.

En Windows 8 se han realizado muchas optimizaciones en el uso de capas y se recomienda probar a usar las API de capa en lugar de FillGeometry siempre que sea posible.

PushLayer en Windows 8

La interfaz ID2D1DeviceContext se deriva de la interfaz ID2D1RenderTarget y es clave para mostrar el contenido de Direct2D en Windows 8, para obtener más información sobre esta interfaz, vea Dispositivos y contextos de dispositivo. Con la interfaz de contexto del dispositivo, puede omitir la llamada al método CreateLayer y, a continuación, pasar NULL al método ID2D1DeviceContext::P ushLayer . Direct2D administra automáticamente el recurso de capa y puede compartir recursos entre capas y gráficos de efectos.

Clips alineados con ejes

Si la región que se va a recortar se alinea con el eje de la superficie de dibujo, en lugar de arbitrario. Este caso es adecuado para usar un rectángulo de clip en lugar de una capa. La ganancia de rendimiento es más para la geometría con alias que la geometría antialiased. Para obtener más información sobre los clips alineados con ejes, consulta el tema PushAxisAlignedClip .

Interoperabilidad DXGI: evitar conmutadores frecuentes

Direct2D puede interoperar perfectamente con superficies de Direct3D. Esto es muy útil para crear aplicaciones que represente una mezcla de contenido 2D y 3D. Pero cada cambio entre el dibujo de Direct2D y el contenido de Direct3D afecta al rendimiento.

Cuando se representa en una superficie DXGI, Direct2D guarda el estado de los dispositivos Direct3D mientras se representa y restaura cuando se completa la representación. Cada vez que se completa un lote de representación de Direct2D, el costo de este ahorro y restauración y el costo de vaciar todas las operaciones 2D se pagan y, sin embargo, el dispositivo Direct3D no está vaciado. Por lo tanto, para aumentar el rendimiento, limite el número de conmutadores de representación entre Direct2D y Direct3D.

Conocer el formato de píxel

Al crear un destino de representación, puede usar la estructura D2D1_PIXEL_FORMAT especificar el formato de píxel y el modo alfa que usa el destino de representación. Un canal alfa forma parte del formato de píxel que especifica el valor de cobertura o la información de opacidad. Si un destino de representación no usa el canal alfa, se debe crear mediante el modo alfa D2D1_ALPHA_MODE_IGNORE . Esto ahorra el tiempo dedicado a representar un canal alfa que no es necesario.

Para obtener más información sobre los formatos de píxeles y los modos alfa, vea Formatos de píxeles admitidos y Modos alfa.

Complejidad de la escena

Al analizar los puntos activos de rendimiento en una escena que se representará, saber si la escena está enlazada a velocidad de relleno o enlazada a vértices puede proporcionar información útil.

  • Velocidad de relleno: la velocidad de relleno hace referencia al número de píxeles que una tarjeta gráfica puede representar y escribir en la memoria de vídeo por segundo.
  • Enlazado a vértice: una escena está enlazada a vértices cuando contiene una gran cantidad de geometría compleja.

Descripción de la complejidad de la escena

Puede analizar la complejidad de la escena modificando el tamaño del destino de representación. Si las ganancias de rendimiento son visibles para una reducción proporcional del tamaño del destino de representación, la aplicación está enlazada a velocidad de relleno. De lo contrario, la complejidad de la escena es el cuello de botella de rendimiento.

Cuando una escena está enlazada a velocidad de relleno, reducir el tamaño del destino de representación puede mejorar el rendimiento. Esto se debe a que el número de píxeles que se van a representar se reducirá proporcionalmente con el tamaño del destino de representación.

Cuando una escena está enlazada a vértices, reduzca la complejidad de la geometría. Pero recuerde que esto se hace a costa de la calidad de la imagen. Por lo tanto, se debe tomar una decisión de compensación cuidadosa entre la calidad deseada y el rendimiento necesario.

Mejora del rendimiento de las aplicaciones de impresión de Direct2D

Direct2D ofrece compatibilidad con la impresión. Puede enviar los mismos comandos de dibujo de Direct2D (en forma de listas de comandos de Direct2D) al control de impresión de Direct2D para imprimir, si no sabe qué dispositivos está dibujando o cómo se traduce el dibujo a la impresión.

Puede ajustar aún más su uso del control de impresión direct2D y los comandos de dibujo de Direct2D para proporcionar resultados de impresión con un mejor rendimiento.

El control de impresión de Direct2D genera mensajes de depuración cuando ve un patrón de código direct2D que conduce a reducir la calidad o el rendimiento de impresión (como los patrones de código enumerados más adelante en este tema) para recordarle dónde puede evitar problemas de rendimiento. Para ver esos mensajes de depuración, debe habilitar la capa de depuración de Direct2D en el código. Consulte Depurar mensajes para obtener instrucciones para habilitar la salida del mensaje de depuración.

Establecer los valores de propiedad correctos al crear el control de impresión D2D

Hay tres propiedades que puede establecer al crear el control de impresión de Direct2D . Dos de estas propiedades afectan al modo en que el control de impresión de Direct2D controla determinados comandos de Direct2D y, a su vez, afectan al rendimiento general.

  • Modo de subconjunto de fuentes: los subconjuntos de recursos de fuente del control de impresión direct2D usados en cada página antes de enviar la página que se va a imprimir. Este modo reduce el tamaño de los recursos de página necesarios para imprimir. Dependiendo del uso de fuentes en la página, puede elegir diferentes modos de subconjunto de fuentes para obtener el mejor rendimiento.
    • D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT proporciona el mejor rendimiento de impresión en la mayoría de los casos. Cuando se establece en este modo, el control de impresión de Direct2D usa una estrategia heurística para decidir cuándo se van a agrupar las fuentes.
    • Para trabajos de impresión breves con 1 o 2 páginas, se recomienda D2D1_PRINT_FONT_SUBSET_MODE_EACHPAGE , donde los subconjuntos de controles de impresión direct2D e insertan recursos de fuente en cada página y, a continuación, descarta ese subconjunto de fuentes después de imprimir la página. Esta opción garantiza que cada página se pueda imprimir inmediatamente después de que se genere, pero aumente ligeramente el tamaño de los recursos de página necesarios para imprimir (con subconjuntos de fuentes normalmente grandes).
    • Para trabajos de impresión con muchas páginas de textos y tamaños de fuente pequeños (como 100 páginas de texto que usa una sola fuente), se recomienda D2D1_PRINT_FONT_SUBSET_MODE_NONE, donde el control de impresión direct2D no agrupa los recursos de fuente en absoluto; en su lugar, envía los recursos de fuente originales junto con la página que usa primero la fuente y vuelve a usar los recursos de fuente para las páginas posteriores sin reenviarlos.
  • PPP de rasterización: cuando el control de impresión de Direct2D necesita rasterizar comandos direct2D durante la conversión de Direct2D-XPS, usa este PPP para la rasterización. En otras palabras, si la página no tiene ningún contenido rasterizado, establecer ningún PPP no cambiará el rendimiento y la calidad. Dependiendo del uso de rasterización en la página, puede elegir diferentes DPIs de rasterización para el mejor equilibrio entre fidelidad y rendimiento.
    • 150 es el valor predeterminado si no especifica un valor al crear el control de impresión direct2D , que es el mejor equilibrio de calidad de impresión y rendimiento de impresión en la mayoría de los casos.
    • Los valores más altos de PPP suelen dar lugar a una mejor calidad de impresión (como en más detalles conservados), pero a un menor rendimiento debido a los mapas de bits más grandes que genera. No se recomienda ningún valor de PPP mayor que 300, ya que eso no introducirá información adicional visualmente percebible por los ojos humanos.
    • Un ppp inferior puede significar un mejor rendimiento, pero también puede producir una menor calidad.

Evitar el uso de determinados patrones de dibujo de Direct2D

Hay diferencias entre lo que Direct2D puede representar visualmente y lo que el subsistema de impresión puede mantener y transportar a lo largo de toda la canalización de impresión. El control de impresión de Direct2D cierra esos huecos aproximando o rasterizando primitivos de Direct2D que el subsistema de impresión no admite de forma nativa. Esta aproximación suele provocar una menor fidelidad de impresión, un menor rendimiento de impresión o ambos. Por lo tanto, aunque un cliente pueda usar los mismos patrones de dibujo para la representación de pantalla e impresión, no es ideal en todos los casos. Es mejor no usar estos primitivos y patrones direct2D tanto como sea posible para la ruta de impresión, o para hacer su propia rasterización donde tiene control total de la calidad y el tamaño de las imágenes rasterizadas.

Esta es una lista de casos en los que el rendimiento y la calidad de impresión no serán ideales y es posible que quiera considerar la posibilidad de variar la ruta de acceso del código para obtener un rendimiento de impresión óptimo.

  • Evite usar el modo de mezcla primitivo distinto de D2D1_PRIMITIVE_BLEND_SOURCEOVER.
  • Evite usar modos de composición al dibujar una imagen distinta de D2D1_COMPOSITE_MODE_SOURCE_OVER y D2D1_COMPOSITE_MODE_DESTINATION_OVER.
  • Evite dibujar un archivo meta de GDI.
  • Evite insertar un recurso de capa que copie el fondo de origen (llamando a PushLayer con pasar D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND al struct de D2D1_LAYER_PARAMETERS1 ).
  • Evite crear pincel de mapa de bits o pincel de imagen con D2D1_EXTEND_MODE_CLAMP. Se recomienda usar D2D1_EXTEND_MODE_MIRROR si no le importan los píxeles fuera de la imagen enlazada en absoluto (como, se sabe que la imagen adjunta al pincel es mayor que la región de destino rellenada).
  • Evite dibujar mapas de bits con transformaciones de perspectiva.

Dibujar texto de forma directa y sin formato

Direct2D tiene varias optimizaciones al representar textos para mostrar para mejorar el rendimiento o mejorar la calidad visual. Pero no todas las optimizaciones mejoran el rendimiento y la calidad de impresión, ya que la impresión en papel suele estar en un PPP mucho mayor, y la impresión no necesita adaptarse a escenarios como la animación. Por lo tanto, se recomienda dibujar el texto original o glifos directamente y evitar cualquiera de las siguientes optimizaciones al crear la lista de comandos para imprimir.

  • Evite dibujar texto con el método FillOpacityMask .
  • Evite dibujar texto en modo con alias.

Dibujar los mapas de bits originales siempre que sea posible

Si el mapa de bits de destino es jpeg, PNG, TIFF o JPEG-XR, puede crear un mapa de bits WIC desde un archivo de disco o desde una secuencia en memoria, cree un mapa de bits de Direct2D a partir de ese mapa de bits WIC mediante ID2D1DeviceContext::CreateBitmapFromWicBitmap y, por último, pase directamente ese mapa de bits de Direct2D al control de impresión de Direct2D sin ninguna manipulación adicional. Al hacerlo, el control de impresión de Direct2D es capaz de reutilizar la secuencia de mapa de bits, lo que suele dar lugar a un mejor rendimiento de impresión (omitiendo la codificación y descodificación redundantes del mapa de bits) y una mejor calidad de impresión (cuando se conservan metadatos, como perfiles de color, en el mapa de bits).

Dibujar el mapa de bits original proporciona la siguiente ventaja para las aplicaciones.

  • En general, la impresión de Direct2D conserva la información original (sin pérdida o ruido) hasta tarde en la canalización, especialmente cuando las aplicaciones no conocen (o no quieren saber) los detalles de la canalización de impresión (como la impresora en la que está imprimiendo, qué PPP es la impresora de destino, etc.).
  • En muchos casos, retrasar la rasterización del mapa de bits significa un mejor rendimiento (como al imprimir una foto de 96dpi en una impresora de 600dpi).
  • En ciertos casos, pasar las imágenes originales es la única manera de respetar la alta fidelidad (como los perfiles de color incrustados).

Sin embargo, no puede optar por esta optimización porque:

  • Al consultar la información de la impresora y la rasterización temprana, puede rasterizar el contenido en sí mismo con control total de la apariencia final en papel.
  • En algunos casos, la rasterización temprana podría mejorar realmente el rendimiento de un extremo a otro de una aplicación (como imprimir fotos de tamaño de cartera).
  • En algunos casos, pasar los mapas de bits originales requiere un cambio significativo de la arquitectura de código existente (como la carga de retraso de imagen y las rutas de actualización de recursos que se encuentran en determinadas aplicaciones).

Conclusión

Aunque Direct2D está acelerado por hardware y está pensado para un alto rendimiento, debe usar las características correctamente para maximizar el rendimiento. Las técnicas que hemos examinado aquí se derivan del estudio de escenarios comunes y es posible que no se apliquen a todos los escenarios de aplicación.