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


Начало работы (DirectXMath)

Библиотека DirectXMath реализует оптимальный и переносимый интерфейс для арифметических и линейных алгебровых операций с векторами с плавающей запятой с одной точностью (2D, 3D и 4D) или матрицами (3×3 и 4×4). Библиотека имеет ограниченную поддержку целочисленных векторных операций. Эти операции широко используются графическими программами для отрисовки и анимации. Векторы двойной точности (включая длинные, короткие или байты) не поддерживаются, а операции с целым вектором ограничены.

Библиотека доступна на различных платформах Windows. Так как библиотека предоставляет функции, недоступные ранее, эта версия заменяет следующие библиотеки:

  • Библиотека Xbox Math, предоставляемая заголовком Xboxmath.h
  • Библиотека D3DX 9, предоставляемая библиотеками DLL D3DX 9
  • Математическая библиотека D3DX 10, предоставляемая через библиотеки DLL D3DX 10
  • Библиотека XNA Math, предоставляемая заголовком xnamath.h в пакете SDK Для DirectX и XDK для Xbox 360

В этих разделах описаны основы начала работы.

Скачать

Библиотека DirectXMath включена в windows SDK. Кроме того, вы можете скачать его с сайта GitHub/Microsoft/DirectXMath. Этот сайт также содержит связанные примеры проектов.

требования к системе Run-Time

Библиотека DirectXMath использует специализированные инструкции процессора для векторных операций, когда они доступны. Чтобы программа не создавала ошибки "неизвестных исключений инструкций", проверка для поддержки процессора, вызвав XMVerifyCPUSupport перед использованием библиотеки DirectXMath.

Ниже приведены основные требования к поддержке времени выполнения библиотеки DirectXMath.

  • Для компиляции по умолчанию на платформе Windows (x86/x64) требуется поддержка инструкций SSE/SSE2.
  • Для выполнения по умолчанию на платформе Windows RT требуется поддержка инструкций ARM-NEON.
  • Для компиляции с определенным _XM_NO_INTRINSICS_ требуется только поддержка стандартных операций с плавающей запятой.

Примечание

При вызове XMVerifyCPUSupport включите <windows.h> перед включением <DirectXMath.h>. Это единственная функция в библиотеке, которая требует содержимого из <windows.h> , поэтому вам не нужно включать <windows.h> в каждый модуль, использующий <DirectXMath.h>.

 

Общие сведения о проектировании

Библиотека DirectXMath в основном поддерживает язык программирования C++. Библиотека реализуется с помощью встроенных подпрограмм в файлах заголовков DirectXMath*.inl, DirectXPackedVector.inl и DirectXCollision.inl. В этой реализации используются встроенные функции высокопроизводительного компилятора.

Библиотека DirectXMath предоставляет:

  • Реализация с использованием встроенных функций SSE/SSE2.
  • Реализация без встроенных функций.
  • Реализация с использованием встроенных функций ARM-NEON.

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

Соглашение о матрицах

DirectXMath использует матрицы основных строк, векторы строк и предварительное умножение. Ручность определяется используемой версией функции (RH или LH). В противном случае функция работает с левой или правой координатами представления.

Для справки Direct3D исторически использовала левую систему координат, матрицы основных строк, векторы строк и предварительное умножение. Современная версия Direct3D не имеет строгих требований к левым и праворуким координатам, и обычно шейдеры HLSL по умолчанию используют матрицы с основными столбцами. Дополнительные сведения см. в разделе Упорядочение матриц HLSL .

Основное использование

Чтобы использовать функции библиотеки DirectXMath, включите заголовки DirectXMath.h, DirectXPackedVector.h, DirectXColors.h и (или) DirectXCollision.h. Заголовки находятся в пакете средств разработки программного обеспечения windows для приложений Магазина Windows.

Рекомендации по использованию типов

Типы XMVECTOR и XMMATRIX являются рабочими лошадями для библиотеки DirectXMath. Каждая операция использует или создает данные этих типов. Работа с ними является ключом к использованию библиотеки. Однако, так как DirectXMath использует наборы инструкций SIMD, эти типы данных распространяются на ряд ограничений. Очень важно понимать эти ограничения, если вы хотите использовать функции DirectXMath.

XMVECTOR следует рассматривать как прокси-сервер для аппаратного регистра SIMD, а XMMATRIX — как прокси-сервер для логической группировки четырех аппаратных регистров SIMD. Эти типы имеют заметки, чтобы указать, что для правильной работы им требуется 16-байтовое выравнивание. Компилятор автоматически поместит их правильно в стек, когда они используются в качестве локальной переменной, или помещают в сегмент данных, когда они используются в качестве глобальной переменной. При использовании соответствующих соглашений их также можно безопасно передавать в качестве параметров в функцию (дополнительные сведения см. в разделе Соглашения о вызовах ).

Выделения из кучи, однако, являются более сложными. Поэтому необходимо соблюдать осторожность при использовании XMVECTOR или XMMATRIX в качестве члена класса или структуры, выделяемой из кучи. В Windows x64 все выделения кучи выровнены по 16 байтам, но для Windows x86 они выровнены только по 8 байтам. Существуют варианты выделения структур из кучи с 16-байтным выравниванием (см. раздел Правильное выравнивание выделений). Для программ C++ можно использовать перегрузки операторов new/delete/new[]/delete[] (глобально или для конкретного класса), чтобы при необходимости обеспечить оптимальное выравнивание.

Примечание

В качестве альтернативы применению выравнивания в классе C++ напрямую путем перегрузки new/delete можно использовать идиому pImpl. Если убедиться, что класс Impl согласован с помощью _aligned_malloc внутренне, вы можете свободно использовать выровненные типы во внутренней реализации. Это хороший вариант, если класс public является классом ссылки среда выполнения Windows или предназначен для использования с std::shared_ptr<>, что в противном случае может нарушить тщательное выравнивание.

 

Однако зачастую проще и компактнее избежать использования XMVECTOR или XMMATRIX непосредственно в классе или структуре. Вместо этого в качестве элементов структуры используйте XMFLOAT3, XMFLOAT4, XMFLOAT4X3, XMFLOAT4X4 и т. д. Кроме того, вы можете использовать функции векторной загрузки и хранения векторов , чтобы эффективно перемещать данные в локальные переменные XMVECTOR или XMMATRIX , выполнять вычисления и сохранять результаты. Существуют также функции потоковой передачи (XMVector3TransformStream, XMVector4TransformStream и т. д.), которые эффективно работают непосредственно с массивами этих типов данных.

Создание векторов

КОНСТАНТНЫЕ ВЕКТОРЫ

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

  • При загрузке скалярной константы во все элементы XMVECTOR используйте XMVectorReplicate или XMVectorReplicateInt.

    XMVECTOR vFive = XMVectorReplicate( 5.f );
    
  • При использовании векторной константы с разными фиксированными значениями в качестве XMVECTOR используйте структуры XMVECTORF32, XMVECTORU32, XMVECTORI32 или XMVECTORU8 . Затем на них можно ссылаться в любом месте, где будет передаваться значение XMVECTOR .

    static const XMVECTORF32 vFactors = { 1.0f, 2.0f, 3.0f, 4.0f };
    

    Примечание

    Не используйте списки инициализаторов непосредственно с XMVECTOR (то есть XMVECTOR v = { 1.0f, 2.0f, 3.0f, 4.0f }). Такой код неэффективен и не переносим на всех платформах, поддерживаемых DirectXMath.

     

  • DirectXMath включает ряд предварительно определенных глобальных констант, которые можно использовать в коде (g_XMOne, g_XMOne3, g_XMTwo, g_XMOneHalf, g_XMHalfPi, g_XMPi и т. д.). Выполните поиск значений XMGLOBALCONST в заголовке DirectXMath.h.

  • Существует набор векторных констант для общих цветов RGB (красный, зеленый, синий, желтый и т. д.). Дополнительные сведения об этих константах вектора см. в разделах DirectXColors.h и пространство имен DirectX::Colors.

ВЕКТОРЫ ИЗ ПЕРЕМЕННЫХ

  • При создании вектора из одной скалярной переменной см. статьи XMVectorReplicate и XMVectorReplicateInt.

    XMVECTOR v = XMVectorReplicate( f  );
    
  • При создании вектора из четырех скалярных переменных см. статьи XMVectorSet и XMVectorSetInt.

    XMVECTOR v = XMVectorSet( fx, fy, fz, fw );
    

ВЕКТОРЫ ИЗ ВЕКТОРОВ

  • При создании вектора из другого вектора с определенным компонентом, заданным в переменную, можно использовать функции векторного метода доступа.

    XMVECTOR v2 = XMVectorSetW( v1, fw );
    
  • При создании вектора из другого вектора с реплицированным одним компонентом используйте XMVectorSplatX, XMVectorSplatY, XMVectorSplatZ и XMVectorSplatW.

    XMVECTOR vz = XMVectorSplatZ( v );
    
  • При создании вектора из другого вектора или пары векторов с переупорядоченными компонентами см. статьи XMVectorSwizzle и XMVectorPermute.

    XMVECTOR v2 = XMVectorSwizzle<XM_SWIZZLE_Z, XM_SWIZZLE_Y, XM_SWIZZLE_W, XM_SWIZZLE_X>( v1 );
    
    XMVECTOR v3 = XMVectorPermute<XM_PERMUTE_0W, XM_PERMUTE_1X, XM_PERMUTE_0X, XM_PERMUTE_1Z>( v1, v2 );
    

ВЕКТОРЫ ИЗ ПАМЯТИ

Извлечение компонентов из векторов

Обработка SIMD наиболее эффективна, когда данные загружаются в регистры SIMD и полностью обрабатываются перед извлечением результатов. Преобразование скалярных и векторных форм неэффективно, поэтому рекомендуется делать это только при необходимости. По этой причине функции в библиотеке DirectXMath, создающие скалярное значение, возвращаются в векторной форме, где скалярный результат реплицируется в результирующем векторе (то есть XMVector2Dot, XMVector3Length и т. д.). Тем не менее, если вам нужны скалярные значения, вот несколько вариантов, как это сделать:

  • Если вычисляется один скалярный ответ, следует использовать функции векторного метода доступа :

    float f = XMVectorGetX( v );
    
  • Если требуется извлечь несколько компонентов вектора, рассмотрите возможность сохранения вектора в структуре памяти и считывания его обратно. Пример:

    XMFLOAT4A t;
    XMStoreFloat4A( &t, v );
    // t.x, t.y, t.z, and t.w can be individually accessed now
    
  • Наиболее эффективной формой векторной обработки является использование потоковой передачи памяти в память, когда входные данные загружаются из памяти (с помощью функций векторной загрузки), обрабатываются полностью в формате SIMD, а затем записываются в память (с помощью функций хранилища векторов).

Руководство по программированию DirectXMath