Поделиться через


Повышение производительности приложений Direct2D

Хотя Direct2D является аппаратным ускорением и предназначен для высокой производительности, необходимо правильно использовать функции, чтобы максимизировать пропускную способность. Приведенные здесь методы основаны на изучении распространенных сценариев и могут применяться не ко всем сценариям приложений. Таким образом, тщательное понимание поведения приложения и целей производительности может помочь достичь нужных результатов.

Использование ресурсов

Ресурс — это выделение в виде видео или системной памяти. Примерами ресурсов являются точечные изображения и кисти.

В Direct2D ресурсы можно создавать как в программном, так и аппаратном обеспечении. Создание и удаление ресурсов на оборудовании являются дорогостоящими операциями, так как для взаимодействия с видео карта требуются огромные затраты. Давайте посмотрим, как Direct2D отрисовывает содержимое в целевой объект.

В Direct2D все команды отрисовки заключаются между вызовом BeginDraw и вызовом EndDraw. Эти вызовы выполняются к целевому объекту отрисовки. Перед вызовом операций отрисовки необходимо вызвать метод BeginDraw . После вызова BeginDraw контекст обычно создает пакет команд отрисовки, но откладывает обработку этих команд до тех пор, пока не будет выполнена одна из следующих инструкций:

  • Произошло endDraw. При вызове Метода EndDraw выполняется выполнение всех пакетных операций рисования и возвращается состояние операции.
  • Вы выполняете явный вызов Flush. Метод Flush вызывает обработку пакета и выполнение всех ожидающих команд.
  • Буфер, содержащий команды отрисовки, заполнен. Если этот буфер заполняется до выполнения двух предыдущих условий, команды отрисовки удаляются.

До очистки примитивов Direct2D сохраняет внутренние ссылки на соответствующие ресурсы, такие как растровые изображения и кисти.

Повторное использование ресурсов

Как уже упоминалось, создание и удаление ресурсов на оборудовании обходится дорого. Поэтому по возможности повторно используйте ресурсы. Возьмем пример создания точечных рисунков при разработке игр. Как правило, точечные изображения, составляющие сцену в игре, создаются одновременно со всеми различными вариантами, необходимыми для последующей отрисовки кадров в кадр. Во время фактической отрисовки и повторной отрисовки сцены эти растровые изображения используются повторно, а не повторно создаются.

Примечание

Вы не можете повторно использовать ресурсы для операции изменения размера окна. При изменении размера окна необходимо повторно создать некоторые ресурсы, зависящие от масштабирования, например совместимые целевые объекты отрисовки, и, возможно, ресурсы слоя, так как содержимое окна необходимо перерисовывать. Это может быть важно для поддержания общего качества отрисовки сцены.

 

Ограничение использования очистки

Так как метод Flush вызывает обработку пакетных команд отрисовки, рекомендуется не использовать его. В большинстве распространенных сценариев оставьте управление ресурсами в Direct2D.

Растровые изображения

Как упоминалось ранее, создание и удаление ресурсов являются очень дорогостоящими операциями на оборудовании. Растровое изображение — это тип ресурса, который часто используется. Создание растровых изображений на карта видео является дорогостоящим. Повторное их использование может помочь ускорить выполнение приложения.

Создание больших растровых изображений

Видеоадаптеры обычно имеют минимальный размер выделения памяти. Если запрашивается выделение, которое меньше этого, выделяется ресурс такого минимального размера, а избыток памяти тратится впустую и недоступен для других вещей. Если требуется много мелких растровых изображений, лучше выделить одно крупное растровое изображение и сохранить все содержимое мелких растровых рисунков в этом крупном растровом рисунке. Затем вложенные области более крупного растрового рисунка можно считать там, где требуются более мелкие растровые изображения. Часто между мелкими растровыми изображениями следует включать заполнение (прозрачные черные пиксели), чтобы избежать взаимодействия между небольшими изображениями во время операций. Это также называется атласом, и он имеет преимущество в том, что он позволяет сократить затраты на создание растровых изображений и тратить память на небольшие выделения растровых изображений. Рекомендуется, чтобы большинство растровых изображений не превышало 64 КБ, а количество растровых изображений не превышало 4 КБ.

Создание атласа точечных рисунков

Существуют некоторые распространенные сценарии, в которых точечный атлас может служить очень хорошо. Небольшие растровые изображения могут храниться внутри большого растрового рисунка. Эти небольшие растровые изображения можно извлечь из более крупного растрового рисунка, если они нужны, указав целевой прямоугольник. Например, приложение может нарисовать несколько значков. Все растровые изображения, связанные с значками, можно загрузить в большой растровый рисунок спереди. А во время отрисовки их можно извлечь из большого растрового изображения.

Примечание

Точечный рисунок Direct2D, созданный в видеопамях, ограничен максимальным размером растрового изображения, поддерживаемым адаптером, на котором оно хранится. Создание растрового изображения, превышающего размер, может привести к ошибке.

 

Примечание

Начиная с Windows 8, Direct2D включает эффект Atlas, который может упростить этот процесс.

 

Создание общих растровых изображений

Создание общих растровых изображений позволяет расширенным вызывающим объектам создавать объекты точечных изображений Direct2D, которые поддерживаются непосредственно существующим объектом, уже совместимым с целевым объектом отрисовки. Это позволяет избежать создания нескольких поверхностей и снизить нагрузку на производительность.

Примечание

Общие растровые изображения обычно ограничиваются целевыми объектами программного обеспечения или целевыми объектами, совместимыми с DXGI. Используйте методы CreateBitmapFromDxgiSurface, CreateBitmapFromWicBitmap и CreateSharedBitmap для создания общих растровых изображений.

 

Копирование растровых изображений

Создание поверхности DXGI является дорогостоящей операцией, поэтому при возможности повторно используйте существующие поверхности. Даже в программном обеспечении, если растровое изображение в основном находится в нужном виде, за исключением небольшой части, лучше обновить эту часть, чем выбросить всю растровую диаграмму и создать все заново. Хотя вы можете использовать CreateCompatibleRenderTarget для достижения одинаковых результатов, отрисовка обычно является гораздо более дорогостоящей операцией, чем копирование. Это связано с тем, что для улучшения локальности кэша оборудование фактически не хранит растровое изображение в том же порядке памяти, что и растровое изображение. Вместо этого растровое изображение может быть закручено. Переворачивается от ЦП либо драйвером (который работает медленно и используется только в нижней части), либо диспетчером памяти на GPU. Из-за ограничений на то, как данные записываются в целевой объект отрисовки при отрисовке, целевые объекты отрисовки обычно либо не закручены, либо переворачены способом, который является менее оптимальным, чем это возможно, если вы знаете, что никогда не нужно выполнять отрисовку на поверхности. Таким образом, методы CopyFrom* предоставляются для копирования прямоугольников из источника в растровое изображение Direct2D.

CopyFrom можно использовать в любой из трех форм:

Использование мозаичного растрового изображения поверх штрихового элемента

Отрисовка пунктирной линии является очень дорогостоящей операцией из-за высокого качества и точности базового алгоритма. В большинстве случаев, не связанных с прямой геометрией, один и тот же эффект можно создать быстрее с помощью мозаичного растрового изображения.

Общие рекомендации по отрисовке сложного статического содержимого

Кэшируйте содержимое, если один и тот же кадр содержимого отображается по кадру, особенно если сцена сложная.

Существует три метода кэширования, которые можно использовать:

  • Полное кэширование сцены с использованием цветового растрового изображения.
  • Для примитивного кэширования с помощью растрового изображения A8 и метода FillOpacityMask .
  • Кэширование по примитиву с использованием реализаций геометрии.

Рассмотрим каждую из них более подробно.

Полное кэширование сцены с использованием цветового растрового изображения

При отрисовке статического содержимого в таких сценариях, как анимация, создайте другое полноцветное растровое изображение вместо записи непосредственно на растровое изображение экрана. Сохраните текущий целевой объект, задайте для целевого объекта промежуточное растровое изображение и отрисовка статического содержимого. Затем вернитесь к исходному растровом рисунку экрана и нарисуйте на нем промежуточное растровое изображение.

Ниже приведен пример:

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

В этом примере используются промежуточные растровые изображения для кэширования и переключение растрового изображения, на которое указывает контекст устройства при отрисовки. Это позволяет избежать необходимости создания совместимого целевого объекта отрисовки для той же цели.

Примитивное кэширование с помощью растрового изображения A8 и метода FillOpacityMask

Если полная сцена не является статической, а состоит из статических элементов, таких как геометрия или текст, можно использовать метод кэширования по примитиву. Этот метод сохраняет характеристики сглаживания кэшируемого примитива и работает с изменяющимися типами кистей. В нем используется растровое изображение A8, где A8 — это своего рода формат пикселей, представляющий альфа-канал с 8 битами. Растровые изображения A8 полезны для рисования геометрии и текста в качестве маски. Если необходимо управлять непрозрачностью статического содержимого, вместо управления самим содержимым можно преобразовать, повернуть, наклонить или масштабировать непрозрачность маски.

Ниже приведен пример:

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

Кэширование по примитиву с использованием реализаций геометрии

Другой метод кэширования по примитиву, называемый реализациями геометрии, обеспечивает большую гибкость при работе с геометрией. Если требуется многократно рисовать с псевдонимами или сглаживания геометрические объекты, их быстрее преобразовать в геометрические реализации и многократно рисовать реализации, чем многократно рисовать сами геометрические объекты. Реализации геометрии также обычно потребляют меньше памяти, чем маски непрозрачности (особенно для больших геометрических объектов), и они менее чувствительны к изменениям масштаба. Дополнительные сведения см. в статье Общие сведения о реализации геометрии.

Ниже приведен пример:

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

Отрисовка геометрии

Использование определенного примитива рисования для рисования геометрии

Используйте более конкретныепримитивные вызовы рисования, такие как DrawRectangle , для универсальных вызовов DrawGeometry . Это связано с тем, что при использовании DrawRectangle геометрия уже известна, поэтому отрисовка выполняется быстрее.

Отрисовка статической геометрии

В сценариях, где геометрия является статической, используйте методы кэширования по примитиву, описанные выше. Маски непрозрачности и реализации геометрии могут значительно повысить скорость отрисовки сцен, содержащих статическую геометрию.

Использование контекста многопоточного устройства

Приложениям, которые ожидают отрисовки значительных объемов сложного геометрического содержимого, следует указать флаг D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTI_THREADED_OPTIMIZATIONS при создании контекста устройства Direct2D . Если этот флаг задан, Direct2D распределяет отрисовку по всем логическим ядрам, присутствующим в системе, что может значительно сократить общее время отрисовки.

Примечания.

  • С Windows 8.1 этот флаг влияет только на отрисовку геометрии пути. Он не влияет на сцены, содержащие только другие примитивные типы (например, текст, растровые изображения или геометрические реализации).
  • Этот флаг также не влияет на отрисовку в программном обеспечении (т. е. при отрисовке на устройстве WARP Direct3D). Чтобы управлять многопоточностью программного обеспечения, вызывающие стороны должны использовать флаг D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS при создании устройства WARP Direct3D.
  • Указание этого флага может увеличить пиковый рабочий набор во время отрисовки, а также увеличить состязание потоков в приложениях, которые уже используют преимущества многопоточной обработки.

Рисование текста с помощью Direct2D

Функция отрисовки текста Direct2D предлагается в двух частях. Первая часть, предоставленная в виде метода ID2D1RenderTarget::D rawText и ID2D1RenderTarget::D rawTextLayout , позволяет вызывающей объекту передавать строковые параметры и параметры форматирования или объект макета текста DWrite для нескольких форматов. Этот параметр должен подходить для большинства вызывающих абонентов. Второй способ отрисовки текста, предоставляемый в виде метода ID2D1RenderTarget::D rawGlyphRun , обеспечивает растеризацию для клиентов, которые уже знают положение глифов, которые они хотят отрисовать. Следующие два общих правила помогут повысить производительность текста при рисовании в Direct2D.

DrawTextLayout и DrawText

И DrawText, и DrawTextLayout позволяют приложению легко отрисовывать текст, отформатированный с помощью API DirectWrite. DrawTextLayout рисует существующий объект DWriteTextLayout в RenderTarget, а DrawText создает макет DirectWrite для вызывающего объекта на основе переданных параметров. Если один и тот же текст должен быть отрисован несколько раз, используйте DrawTextLayout вместо DrawText, так как DrawText создает макет при каждом вызове.

Выбор правильного режима отрисовки текста

Задайте режим антиалиасного текста на D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE явным образом. Качество отрисовки текста в оттенках серого сравнимо с ClearType, но выполняется гораздо быстрее.

Кэширование

Используйте полную сцену или кэширование примитивного растрового изображения, как при рисовании других примитивов.

Обрезка произвольной фигуры

На рисунке ниже показан результат применения клипа к изображению.

Изображение, показывающее пример изображения до и после клипа.

Этот результат можно получить с помощью слоев с маской геометрии или метода FillGeometry с помощью кисти непрозрачности.

Ниже приведен пример, в котором используется слой:

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

Ниже приведен пример использования метода 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()); 

В этом примере кода при вызове метода PushLayer вы не передаете слой, созданный приложением. Direct2D создает слой. Direct2D может управлять выделением и уничтожением этого ресурса без какого-либо участия приложения. Это позволяет Direct2D повторно использовать слои внутри системы и применять оптимизацию управления ресурсами.

В Windows 8 было сделано много оптимизаций для использования слоев, и мы рекомендуем по возможности использовать API слоев вместо FillGeometry.

PushLayer в Windows 8

Интерфейс ID2D1DeviceContext является производным от интерфейса ID2D1RenderTarget и является ключом к отображению содержимого Direct2D в Windows 8. Дополнительные сведения об этом интерфейсе см. в разделе Устройства и контексты устройств. С помощью интерфейса контекста устройства можно пропустить вызов метода CreateLayer , а затем передать значение NULL в метод ID2D1DeviceContext::P ushLayer . Direct2D автоматически управляет ресурсом слоя и может совместно использовать ресурсы между слоями и графами эффектов.

Выровненные по оси клипы

Если обрезаемая область выравнивается по оси поверхности рисования, а не произвольно. Этот вариант подходит для использования прямоугольника клипа вместо слоя. Увеличение производительности больше для геометрии с псевдонимом, чем для сглаживания геометрии. Дополнительные сведения о выровненных по оси клипах см. в разделе PushAxisAlignedClip .

Взаимодействие DXGI: избегайте частых переключений

Direct2D может легко взаимодействовать с поверхностями Direct3D. Это очень полезно для создания приложений, которые отображают сочетание двух- и трехмерного содержимого. Но каждый переключатель между рисованием Direct2D и содержимым Direct3D влияет на производительность.

При отрисовке на поверхности DXGI Direct2D сохраняет состояние устройств Direct3D во время отрисовки и восстанавливает его после завершения отрисовки. Каждый раз, когда выполняется отрисовка пакета Direct2D, оплачиваются затраты на это сохранение и восстановление, а также затраты на очистку всех двухмерных операций, и тем не менее устройство Direct3D не сбрасывается. Таким образом, чтобы повысить производительность, ограничьте число переключений отрисовки между Direct2D и Direct3D.

Узнать свой формат пикселей

При создании целевого объекта отрисовки можно использовать структуру D2D1_PIXEL_FORMAT указать формат пикселей и альфа-режим, используемый целевым объектом отрисовки. Альфа-канал является частью формата пикселей, который указывает значение покрытия или сведения о непрозрачности. Если целевой объект отрисовки не использует альфа-канал, его следует создать с помощью D2D1_ALPHA_MODE_IGNORE альфа-режима. Это сэкономить время, затраченное на отрисовку альфа-канала, который не требуется.

Дополнительные сведения о форматах пикселей и альфа-режимах см. в разделе Поддерживаемые форматы пикселей и альфа-режимы.

Сложность сцены

При анализе горячих точек производительности в сцене, которая будет отрисовывается, полезной информацией может быть знание того, привязана ли сцена к скорости заполнения или привязана к вершинам.

  • Частота заполнения. Скорость заполнения — это количество пикселей, которое карта графики может отрисовывать и записывать в видеопамять в секунду.
  • Привязанная вершина. Сцена привязана к вершинам, если она содержит много сложной геометрии.

Общие сведения о сложности сцены

Вы можете проанализировать сложность сцены, изменив размер целевого объекта отрисовки. Если увеличение производительности заметно для пропорционального уменьшения размера целевого объекта отрисовки, приложение будет привязано к скорости заполнения. В противном случае сложность сцены является узким местом производительности.

Если сцена привязана к скорости заполнения, уменьшение размера целевого объекта отрисовки может повысить производительность. Это связано с тем, что количество пикселей для отрисовки будет уменьшено пропорционально размеру целевого объекта отрисовки.

Если сцена привязана к вершинам, уменьшите сложность геометрии. Но помните, что это делается за счет качества изображения. Поэтому следует принять тщательное решение о компромиссе между требуемым качеством и требуемой производительностью.

Повышение производительности приложений для печати Direct2D

Direct2D обеспечивает совместимость с печатью. Вы можете отправить те же команды рисования Direct2D (в виде списков команд Direct2D) в элемент управления печатью Direct2D для печати, если вы не знаете, на каких устройствах выполняется рисование или как документ преобразуется в печать.

Вы можете дополнительно точно настроить их использование элемента управления печатью Direct2D и команд рисования Direct2D, чтобы обеспечить результаты печати с более высокой производительностью.

Элемент управления печатью Direct2D выводит сообщения отладки при отображении шаблона кода Direct2D, что приводит к снижению качества или производительности печати (например, шаблоны кода, перечисленные далее в этом разделе), чтобы напомнить вам, где можно избежать проблем с производительностью. Чтобы просмотреть эти сообщения отладки, необходимо включить уровень отладки Direct2D в коде. Инструкции по включению вывода сообщений отладки см. в разделе Сообщения отладки.

Установка правильных значений свойств при создании элемента управления печатью D2D

Существует три свойства, которые можно задать при создании элемента управления печатью Direct2D . Два из этих свойств влияют на то, как элемент управления печатью Direct2D обрабатывает определенные команды Direct2D, и, в свою очередь, влияют на общую производительность.

  • Режим подмножества шрифта. Элемент управления печатью Direct2D подмножества шрифтов, используемых на каждой странице, перед отправкой страницы на печать. В этом режиме уменьшается размер ресурсов страницы, необходимых для печати. В зависимости от использования шрифта на странице можно выбрать различные режимы подмножества шрифтов для достижения наилучшей производительности.
    • D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT обеспечивает наилучшую производительность печати в большинстве случаев. Если этот режим установлен, элемент управления печатью Direct2D использует эвристическую стратегию, чтобы решить, когда следует использовать шрифты подмножества.
    • Для коротких заданий печати с 1 или 2 страницами рекомендуется D2D1_PRINT_FONT_SUBSET_MODE_EACHPAGE , где элемент управления печатью Direct2D подмножества и внедряет ресурсы шрифта в каждую страницу, а затем удаляет это подмножество шрифта после печати страницы. Этот параметр гарантирует, что каждая страница может быть напечатана сразу после создания, но немного увеличивает размер ресурсов страницы, необходимых для печати (обычно с большими подмножествами шрифтов).
    • Для заданий печати с большим количеством страниц текста и небольшими размерами шрифтов (например, 100 страниц текста, использующего один шрифт), рекомендуется D2D1_PRINT_FONT_SUBSET_MODE_NONE, где элемент управления печатью Direct2D вообще не подмножество ресурсов шрифта; Вместо этого он отправляет исходные ресурсы шрифта вместе со страницей, которая сначала использует шрифт, и повторно использует ресурсы шрифта для последующих страниц без их повторной отправки.
  • Растеризация DPI. Когда элементу управления печатью Direct2D требуется растеризовать команды Direct2D во время преобразования Direct2D-XPS, он использует это разрешение для растеризации. Иными словами, если на странице нет растеризованного содержимого, установка DPI не изменит производительность и качество. В зависимости от использования растеризации на странице можно выбрать различные DPI для растеризации для оптимального баланса между точностью и производительностью.
    • Значение 150 является значением по умолчанию, если не указать значение при создании элемента управления печатью Direct2D , что в большинстве случаев является оптимальным балансом качества и производительности печати.
    • Более высокие значения DPI обычно приводят к лучшему качеству печати (как в более подробных сведениях сохраняются), но более низкая производительность из-за больших растровых изображений, которые он создает. Мы не рекомендуем использовать значение DPI больше 300, так как это не приведет к дополнительной информации, визуально воспринимаемой человеческими глазами.
    • Более низкое разрешение может означать более высокую производительность, но также может привести к снижению качества.

Избегайте использования определенных шаблонов рисования Direct2D

Существуют различия между тем, что Direct2D может представлять визуально, и тем, что подсистема печати может обслуживать и транспортировать по всему конвейеру печати. Элемент управления печатью Direct2D устраняет эти пробелы путем аппроксимации или растеризации примитивов Direct2D, которые подсистема печати изначально не поддерживает. Такое приближение обычно приводит к снижению точности печати, снижению производительности печати или к тому, и Таким образом, хотя клиент может использовать одни и те же шаблоны рисования как для отрисовки экрана, так и для отрисовки печати, это не является идеальным во всех случаях. Рекомендуется не использовать такие примитивы и шаблоны Direct2D как можно больше для пути печати или выполнять собственную растеризацию, при которой у вас есть полный контроль над качеством и размером растрированных изображений.

Ниже приведен список случаев, когда производительность и качество печати не будут идеальными, и вы можете рассмотреть возможность изменения пути кода для оптимальной производительности печати.

  • Избегайте использования режима примитивного наложения, отличного от D2D1_PRIMITIVE_BLEND_SOURCEOVER.
  • Избегайте использования режимов композиции при рисовании изображения, отличного от D2D1_COMPOSITE_MODE_SOURCE_OVER и D2D1_COMPOSITE_MODE_DESTINATION_OVER.
  • Избегайте рисования метафайла GDI.
  • Избегайте отправки ресурса слоя, который копирует исходный фон (вызов PushLayer с передачей D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND в структуру D2D1_LAYER_PARAMETERS1 ).
  • Избегайте создания кисти растрового рисунка или кисти изображения с помощью D2D1_EXTEND_MODE_CLAMP. Рекомендуется использовать D2D1_EXTEND_MODE_MIRROR, если вам не нужны пиксели за пределами границ изображения (например, изображение, прикрепленное к кисти, как известно, больше, чем заполненная целевая область).
  • Избегайте рисования точечных изображений с помощью преобразований перспективы.

Прямое и простое рисование текста

Direct2D имеет несколько оптимизаций при отрисовке текста для отображения для повышения производительности и/или лучшего визуального качества. Но не все оптимизации улучшают производительность и качество печати, так как печать на бумаге обычно имеет гораздо более высокий точек на дюйм, и печати не требуется учитывать такие сценарии, как анимация. Поэтому рекомендуется рисовать исходный текст или глифы напрямую и избегать любой из следующих оптимизаций при создании списка команд для печати.

  • Избегайте рисования текста с помощью метода FillOpacityMask .
  • Избегайте рисования текста в режиме псевдонима.

По возможности нарисуйте исходные растровые изображения

Если целевое растровое изображение — JPEG, PNG, TIFF или JPEG-XR, можно создать растровое изображение WIC из файла диска или потока в памяти, а затем создать растровое изображение Direct2D из этого растрового изображения WIC с помощью ID2D1DeviceContext::CreateBitmapFromWicBitmap и, наконец, напрямую передать его в элемент управления печатью Direct2D без дальнейших действий. Таким образом, элемент управления печатью Direct2D может повторно использовать поток растровых рисунков, что обычно приводит к повышению производительности печати (путем пропуска избыточного кодирования и декодирования растровых рисунков) и повышению качества печати (когда метаданные, такие как цветовые профили, сохраняются в растровом рисунке).

Рисование исходного растрового рисунка обеспечивает следующее преимущество для приложений.

  • Как правило, при печати Direct2D исходные данные сохраняются (без потерь или шума) до конца конвейера, особенно если приложения не знают (или не хотят знать) сведения о конвейере печати (например, на каком принтере выполняется печать, какой DPI является целевым принтером и т. д.).
  • Во многих случаях задержка растрирования растрового изображения означает более высокую производительность (например, при печати фотографии с разрешением 96 точек на дюйм на принтере с разрешением 600 точек на дюйм).
  • В некоторых случаях передача исходных изображений является единственным способом обеспечить высокую точность (например, внедренные цветовые профили).

Однако вы не можете согласиться на такую оптимизацию, так как:

  • Запросив сведения о принтере и раннюю растеризацию, вы можете растеризовать содержимое себя с полным контролем окончательного внешнего вида на бумаге.
  • В некоторых случаях ранняя растеризация может повысить производительность приложения (например, печать фотографий размером с кошельки).
  • В некоторых случаях для передачи исходных растровых изображений требуется значительное изменение существующей архитектуры кода (например, задержка загрузки изображений и пути обновления ресурсов, обнаруженные в определенных приложениях).

Заключение

Хотя Direct2D является аппаратным ускорением и предназначен для высокой производительности, необходимо правильно использовать эти функции, чтобы максимизировать пропускную способность. Методы, которые мы рассмотрели здесь, основаны на изучении распространенных сценариев и могут применяться не ко всем сценариям приложений.