Работа с DirectXMath и D3DXMath
Еще в D3DXMath у нас была возможность умножать, добавлять или вычитать даже делить векторные типы, которые были структурами D3DXVECTOR2, D3DXVECTOR3, D3DXVECTOR4..... Теперь в воплощении DirectXMath у нас есть XMFLOAT2, XMFLOAT3, XMFLOAT4 и XMVECTOR. Если я хочу выполнить какую-либо математическую операцию, я должен выполнить преобразование из XMFLOAT в XMVECTOR в любом случае, если Visual Studio выдает ошибку "Нет определенного пользователем преобразования". Это почему? На самом деле факт, что в новой версии (Windows 8.1, 10) математической библиотеки DirectX векторная работа немного изменилась. Я делаю что-то неправильно...........?!
PS Ну, для Матриц есть другой вопрос, но сейчас давайте поговорим только о векторах. Эти изменения подталкивают сторонних разработчиков к созданию собственной библиотеки Math, и они сделали это.....:)
1 ответ
На самом деле это подробно объясняется в Руководстве по программированию DirectXMath для MSDN:
Типы 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[] (глобальные или специфичные для класса), чтобы обеспечить оптимальное выравнивание при желании.
Однако часто проще и компактнее избежать использования XMVECTOR или XMMATRIX непосредственно в классе или структуре. Вместо этого используйте XMFLOAT3, XMFLOAT4, XMFLOAT4X3, XMFLOAT4X4 и т. Д. В качестве элементов вашей структуры. Кроме того, вы можете использовать функции векторной загрузки и векторного хранения для эффективного перемещения данных в локальные переменные XMVECTOR или XMMATRIX, выполнения вычислений и сохранения результатов. Существуют также потоковые функции (XMVector3TransformStream, XMVector4TransformStream и т. Д.), Которые эффективно работают непосредственно с массивами этих типов данных.
DirectXMath поощряет вас писать эффективный и удобный для SIMD код. Загрузка или сохранение вектора стоит дорого, поэтому вы должны попытаться работать в потоковой модели, в которой вы загружаете данные, много работаете с ними, регистрируете их, а затем записываете результаты.
Тем не менее, я полностью понимаю, что использование является немного сложным для людей, плохо знакомых с SIMD математикой или DirectX в целом, и немного многословно даже для профессиональных разработчиков. Вот почему я также написал оболочку SimpleMath для DirectXMath, которая заставляет его работать больше как классическая математическая библиотека, которую вы ищете для использования XNA Game Studio, например: Vector2
, Vector3
, Matrix
классы с магией C++, покрывающие все явные загрузки и хранилища. Типы SimpleMath аккуратно взаимодействуют с DirectXMath, поэтому вы можете смешивать и сочетать их по своему усмотрению.
Смотрите этот пост в блоге и GitHub.
DirectXMath специально является "встроенной" библиотекой, означающей, что в оптимизированном коде вам не нужно много передавать переменные, а просто вычислять значение внутри вашей большой функции. Библиотека D3DXMath в устаревшей
D3DX9
,D3DX10
,D3DX11
библиотека более старой школы, которая опирается на таблицы указателей на функции и сильно зависит от производительности из-за накладных расходов соглашения о вызовах.Они, конечно, представляют собой различные инженерные компромиссы. D3DXMath мог выполнять большую замену во время выполнения специализированных путей кода процессора, но платил за эту гибкость с помощью соглашения о вызовах и косвенных издержек. DirectXMath, с другой стороны, предполагает базовый уровень SIMD SSE/SSE2 (или AVX на Xbox One), поэтому вы избегаете необходимости обнаружения или косвенного обращения во время выполнения и вместо этого активно используете встраивание.