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


Precision and numerical clipping in effect graphs

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

  • Граф эффектов использует высокую числовую точность или цвета за пределами диапазона [0, 1], и вы хотите убедиться, что они всегда будут доступны.
  • Or, your effect graph relies on the rendering implementation to clamp intermediate colors to the [0, 1] range, and you want to ensure this clamping always occurs

Direct2D часто делит граф эффектов на разделы и отрисовывает каждый раздел в отдельном шаге. Выходные данные некоторых шагов могут храниться в промежуточных текстурах Direct3D, которые по умолчанию имеют ограниченный числовый диапазон и точность. Direct2D не гарантирует, используется ли эти промежуточные текстуры. Это поведение может отличаться в зависимости от возможностей GPU, а также между версиями Windows.

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

Общие сведения о отрисовке эффектов и промежуточных элементах

To render an effect graph, Direct2D first finds the underlying graph of “transforms,” where a transform is a graph node used within an effect. Существуют различные типы преобразований, включая те, которые предоставляют шейдеры Direct3D для использования в Direct2D.

Например, Direct2D может отобразить граф эффектов следующим образом:

граф эффектов с промежуточными текстурами

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

граф эффектов без промежуточных текстур

До Windows 10 Direct2D всегда будет использовать промежуточные текстуры, если в одном графе эффектов использовались несколько шейдеров пикселей. Большинство встроенных эффектов, которые просто настраивают значения цвета (например, яркость или насыщенность) делают это с помощью шейдеров пикселей.

В Windows 10 Direct2D теперь может избежать использования промежуточных текстур в таких случаях. Это достигается посредством внутреннего связывания соседних шейдеров пикселей. Например:

граф эффектов Windows 10 с несколькими шейдерами пикселей и без промежуточных текстур

Обратите внимание, что не все смежные шейдеры пикселей в графе могут быть связаны друг с другом, и поэтому только определенные графы будут производить разные выходные данные в Windows 10. Полные сведения см. в разделе Связывание шейдеров эффектов. Основными ограничениями являются:

  • Эффект не будет связан с эффектами, потребляющими его выходные данные, если первый эффект подключен в качестве входных данных к нескольким эффектам.
  • An effect will not be linked with an effect set as its input, if the first effect samples its input at a different logical position than its output. For example, a Color Matrix effect might be linked with its input, but a Convolution effect will not be.

Built-in effect behavior

Многие встроенные эффекты могут создавать цвета за пределами диапазона [0, 1] в непреднаставленном цветовом пространстве, даже если их входные цвета находятся в этом диапазоне. When this happens, such colors may be subject to numerical clipping. Обратите внимание, что важно учитывать диапазон цветов в неумноженном пространстве, даже если встроенные эффекты обычно создают цвета в умноженном пространстве. This ensures that colors stay within range, even if other effects subsequently unpremultiply them.

Some of the effects which may emit these out-of-range colors offer a “ClampOutput” property. К ним относятся:

При задании свойства ClampOutput значение TRUE для этих эффектов гарантируется, что согласованный результат будет достигнут независимо от факторов, таких как связывание шейдеров. Note that clamping occurs in unpremultiplied space.

Другие встроенные эффекты также могут создавать выходные цвета за пределами диапазона [0, 1] в непрезумированном пространстве, даже если их цвета пикселей (и свойства 'Цвет', если таковые имеются) находятся в этом диапазоне. К ним относятся:

Forcing numerical clipping within an effect graph

While using effects listed above which do not have a ClampOutput property, applications should consider forcing numerical clamping. Это можно сделать, добавив в граф дополнительный эффект, который ограничивает его пиксели. A Color Matrix effect may be used, with its ‘ClampOutput’ property set to TRUE and leaving the ‘ColorMatrix’ property as the default (pass-through) value.

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

Управление точностью промежуточных текстур

Direct2D предоставляет несколько способов управления точностью графа. Прежде чем использовать форматы высокой точности в Direct2D, приложения должны убедиться, что они достаточно поддерживаются GPU. To check this, use ID2D1DeviceContext::IsBufferPrecisionSupported.

Приложения могут создавать устройство Direct3D с помощью WARP (программной эмуляции), чтобы гарантировать поддержку всех точностей буфера независимо от фактической аппаратуры GPU на устройстве. Это рекомендуется в таких сценариях, как применение эффектов к фотографии при сохранении на диске. Even if Direct2D supports high precision buffer formats on the GPU, using WARP is recommended in this scenario on feature level 9.X GPUs, due to the limited precision of shader arithmetic and sampling on some low-power mobile GPUs.

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

Precision selection from ID2D1DeviceContext::SetRenderingControls

Самый простой способ управления точностью промежуточных текстур Direct2D — использовать ID2D1DeviceContext::SetRenderingControls. This controls the precision of all intermediate textures, as long as a precision is not also set manually on effects or transforms directly.

if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  // Get the current rendering controls
  D2D1_RENDERING_CONTROLS renderingControls = {};
  Context->GetRenderingControls(&renderingControls);

  // Switch the precision within the rendering controls and set it
  renderingControls.bufferPrecision = D2D1_BUFFER_PRECISION_32BPC_FLOAT;
  Context->SetRenderingControls(&renderingControls);
}
              

Precision selection from inputs and render targets

Приложения также могут полагаться на точность входных данных в граф эффектов для управления точностью промежуточных текстур. This is true as long as a buffer precision is not specified using ID2D1DeviceContext::SetRenderingControls, and is not set manually on effects and transform directly.

The precisions of inputs to effects are propagated through the graph to select the precision of downstream intermediates. Где сходятся различные ветви в графе эффектов, используется наивысшая точность среди всех входных данных.

The precision selected based on a Direct2D bitmap is determined from its pixel format. The precision selected for an ID2D1ImageSource is determined from the WIC pixel format of the underlying IWICBitmapSource used to create the ID2D1ImageSource. Note that Direct2D doesn’t allow image sources to be created with WIC sources using precisions unsupported by Direct2D and the GPU.

Возможно, Direct2D не может присвоить эффекту уровень точности на основе его входных данных. Это происходит, если эффект не имеет входных данных или когда используется ID2D1CommandList, которая не имеет определенной точности. In this case, the precision of intermediate textures is determined from the bitmap set as the context’s current render target.

Precision selection directly on the effect and transforms

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

Минимальная точность может быть задана с помощью свойства для эффекта следующим образом:

if (Device->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  hr = Effect->SetValue(D2D1_PROPERTY_PRECISION, D2D1_BUFFER_PRECISION_32BPC_FLOAT);
}
              

В реализации эффекта минимальная точность может быть задана с помощью ID2D1RenderInfo::SetOutputPrecision следующим образом:

if (EffectContext->IsBufferPrecisionSupported(D2D1_BUFFER_PRECISION_32BPC_FLOAT))
{
  hr = RenderInfo->SetOutputBuffer(
  D2D1_BUFFER_PRECISION_32BPC_FLOAT,
  D2D1_CHANNEL_DEPTH_4);
}
              

Обратите внимание, что набор точности для эффекта будет распространяться на подчиненные эффекты в том же графе эффектов, если для этих подчиненных эффектов не задана другая точность. The precision set on a transform within an effect does not affect the precision for downstream transform nodes.

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

логика минимальной точности промежуточного буфера