次の方法で共有


ライブラリの内部構造

DirectXMath ライブラリのグローバル定数

呼び出し規約

移植性を高め、データ レイアウトを最適化するには、DirectXMath ライブラリでサポートされている各プラットフォームに適切な呼び出し規則を使用する必要があります。 具体的には、16 バイト境界に揃えて定義されている XMVECTOR オブジェクトをパラメーターとして渡す場合、ターゲット プラットフォームに応じて呼び出し要件のセットが異なります。

For 32 ビット Windows

32 ビット Windows の場合、 __m128 値 (そのプラットフォームで XMVECTOR を実装) を効率的に渡すために使用できる呼び出し規約が 2 つあります。 標準は __fastcall であり、最初の 3 つの __m128 値 (XMVECTOR インスタンス) を SSE/SSE2 レジスタ内の関数への引数として渡すことができます。 __fastcall は残りの引数をスタック経由で渡します。

新しい Microsoft Visual Studio コンパイラは、新しい呼び出し規約 __vectorcall をサポートしています。これにより、最大 6 つの __m128 値 (XMVECTOR インスタンス) を SSE/SSE2 レジスタ内の関数への引数として渡すことができます。 十分なスペースがある場合は、異種ベクトル集合体(XMMATRIX とも呼ばれる)を SSE/SSE2 レジスタ経由で渡すこともできます。

64ビット版Windowsの場合

64 ビット Windows では、 __m128 値を効率的に渡すために 2 つの呼び出し規約が利用できます。 標準は __fastcallであり、これはすべての __m128 値をスタックに渡します。

新しい Visual Studio コンパイラは、最大 6 つの __m128 値 (XMVECTOR インスタンス) を SSE/SSE2 レジスタ内の関数への引数として渡すことができる __vectorcall 呼び出し規約をサポートしています。 十分なスペースがある場合は、異種ベクトル集合体(XMMATRIX とも呼ばれる)を SSE/SSE2 レジスタ経由で渡すこともできます。

ARM版Windowsの場合

ARM & ARM64 上の Windows は、最初の 4 つの __n128 値 (XMVECTOR インスタンス) をレジスタに渡すことをサポートしています。

DirectXMath ソリューション

FXMVECTORGXMVECTORHXMVECTOR、および CXMVECTOR エイリアスは、次の規則をサポートしています。

  • FXMVECTOR エイリアスを使用して、関数の引数として使用される XMVECTOR の最初の 3 つのインスタンスを渡します。
  • GXMVECTOR エイリアスを使用して、関数の引数として使用される XMVECTOR の 4 番目のインスタンスを渡します。
  • HXMVECTOR エイリアスを使用して、関数の引数として使用される XMVECTOR の 5 番目と 6 番目のインスタンスを渡します。 追加の考慮事項については、__vectorcall のドキュメントを参照してください。
  • 引数として使用される XMVECTOR の追加のインスタンスを渡すには、 CXMVECTOR エイリアスを使用します。

Note

出力パラメータの場合は、常に XMVECTOR* または XMVECTOR& を使用し、入力パラメータの前述のルールについては無視します。

 

__vectorcall の制限のため、C++ コンストラクターには GXMVECTOR または HXMVECTOR を使用しないことをお勧めします。 最初の 3 つの XMVECTOR 値には FXMVECTOR を使用し、残りには CXMVECTOR を使用します。

FXMMATRIX および CXMMATRIX エイリアスは、__vectorcall による HVA 引数の受け渡しを活用することをサポートします。

  • FXMMATRIX エイリアスを使用して、最初の XMMATRIX を関数の引数として渡します。 これは、行列の「右側」に 2 つ以上の FXMVECTOR 引数、または 2 つ以上の float、double、または FXMVECTOR 引数がないことを前提としています。 追加の考慮事項については、__vectorcall のドキュメントを参照してください。
  • それ以外の場合は、 CXMMATRIX エイリアスを使用します。

__vectorcall の制限のため、C++ コンストラクターには FXMMATRIX を使用しないことをお勧めします。 CXMMATRIXを使用するだけです。

型エイリアスに加えて、XM_CALLCONV アノテーションを使用して、関数がコンパイラとアーキテクチャに基づいて適切な呼び出し規約 (__fastcall と __vectorcall) を使用するようにする必要があります。 __vectorcall の制限のため、C++ コンストラクターには XM_CALLCONV を使用しないことをお勧めします。

以下は、この規則を説明する宣言例です。

XMMATRIX XM_CALLCONV XMMatrixLookAtLH(FXMVECTOR EyePosition, FXMVECTOR FocusPosition, FXMVECTOR UpDirection);

XMMATRIX XM_CALLCONV XMMatrixTransformation2D(FXMVECTOR ScalingOrigin,  float ScalingOrientation, FXMVECTOR Scaling, FXMVECTOR RotationOrigin, float Rotation, GXMVECTOR Translation);

void XM_CALLCONV XMVectorSinCos(XMVECTOR* pSin, XMVECTOR* pCos, FXMVECTOR V);

XMVECTOR XM_CALLCONV XMVectorHermiteV(FXMVECTOR Position0, FXMVECTOR Tangent0, FXMVECTOR Position1, GXMVECTOR Tangent1, HXMVECTOR T);

XMMATRIX(FXMVECTOR R0, FXMVECTOR R1, FXMVECTOR R2, CXMVECTOR R3)

XMVECTOR XM_CALLCONV XMVector2Transform(FXMVECTOR V, FXMMATRIX M);

XMMATRIX XM_CALLCONV XMMatrixMultiplyTranspose(FXMMATRIX M1, CXMMATRIX M2);

これらの呼び出し規則をサポートするために、これらの型エイリアスは次のように定義されます (コンパイラがレジスタ内渡しを考慮するには、パラメータを値で渡す必要があります)。

32ビットWindowsアプリの場合

__fastcall を使用する場合:

typedef const XMVECTOR  FXMVECTOR;
typedef const XMVECTOR& GXMVECTOR;
typedef const XMVECTOR& HXMVECTOR;
typedef const XMVECTOR& CXMVECTOR;
typedef const XMMATRIX& FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

__vectorcall を使用する場合。

typedef const XMVECTOR  FXMVECTOR;
typedef const XMVECTOR  GXMVECTOR;
typedef const XMVECTOR  HXMVECTOR;
typedef const XMVECTOR& CXMVECTOR;
typedef const XMMATRIX  FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

64ビットネイティブWindowsアプリの場合

__fastcall を使用する場合:

typedef const XMVECTOR& FXMVECTOR;
typedef const XMVECTOR& GXMVECTOR;
typedef const XMVECTOR& HXMVECTOR;
typedef const XMVECTOR& CXMVECTOR;
typedef const XMMATRIX& FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

__vectorcall を使用する場合。

typedef const XMVECTOR  FXMVECTOR;
typedef const XMVECTOR  GXMVECTOR;
typedef const XMVECTOR  HXMVECTOR;
typedef const XMVECTOR& CXMVECTOR;
typedef const XMMATRIX  FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

ARM 版 Windows

typedef const XMVECTOR  FXMVECTOR;
typedef const XMVECTOR  GXMVECTOR;
typedef const XMVECTOR& CXMVECTOR;
typedef const XMMATRIX& FXMMATRIX;
typedef const XMMATRIX& CXMMATRIX;

Note

すべての関数はインラインで宣言されており、多くの場合、コンパイラはこれらの関数に対して呼び出し規約を使用する必要はありませんが、関数をインライン化しない方が効率的であるとコンパイラが判断するケースもあり、このような場合には、各プラットフォームで可能な限り最適な呼び出し規約が必要になります。

 

グラフィックスライブラリのタイプの等価性

DirectXMath ライブラリの使用をサポートするために、多くの DirectXMath ライブラリの型と構造体は、 D3DDECLTYPE 型と D3DFORMAT 型、および DXGI_FORMAT 型の Windows 実装と同等です。

DirectXMath D3DDECLTYPE D3DFORMAT DXGI_FORMAT
XMBYTE2 DXGI_FORMAT_R8G8_SINT
XMBYTE4 D3DDECLTYPE_BYTE4 (Xbox のみ) D3DFMT_x8x8x8x8 DXGI_FORMAT_x8x8x8x8_SINT
XMBYTEN2 D3DFMT_V8U8 DXGI_FORMAT_R8G8_SNORM
XMBYTEN4 D3DDECLTYPE_BYTE4N (Xbox のみ) D3DFMT_x8x8x8x8 DXGI_FORMAT_x8x8x8x8_SNORM
XMCOLOR D3DDECLTYPE_D3DCOLOR D3DFMT_A8R8G8B8 DXGI_FORMAT_B8G8R8A8_UNORM (DXGI 1.1+)
XMDEC4 D3DDECLTYPE_DEC4 (Xbox のみ) D3DDECLTYPE_DEC3 (Xbox のみ)
XMDECN4 D3DDECLTYPE_DEC4N (Xbox のみ) D3DDECLTYPE_DEC3N (Xbox のみ)
XMFLOAT2 D3DDECLTYPE_FLOAT2 D3DFMT_G32R32F DXGI_FORMAT_R32G32_FLOAT
XMFLOAT2A D3DDECLTYPE_FLOAT2 D3DFMT_G32R32F DXGI_FORMAT_R32G32_FLOAT
XMFLOAT3 D3DDECLTYPE_FLOAT3 DXGI_FORMAT_R32G32B32_FLOAT
XMFLOAT3A D3DDECLTYPE_FLOAT3 DXGI_FORMAT_R32G32B32_FLOAT
XMFLOAT3PK DXGI_FORMAT_R11G11B10_FLOAT
XMFLOAT3SE DXGI_FORMAT_R9G9B9E5_SHAREDEXP
XMFLOAT4 D3DDECLTYPE_FLOAT4 D3DFMT_A32B32G32R32F DXGI_FORMAT_R32G32B32A32_FLOAT
XMFLOAT4A D3DDECLTYPE_FLOAT4 D3DFMT_A32B32G32R32F DXGI_FORMAT_R32G32B32A32_FLOAT
XMHALF2 D3DDECLTYPE_FLOAT16_2 D3DFMT_G16R16F DXGI_FORMAT_R16G16_FLOAT
XMHALF4 D3DDECLTYPE_FLOAT16_4 D3DFMT_A16B16G16R16F DXGI_FORMAT_R16G16B16A16_FLOAT
XMINT2 DXGI_FORMAT_R32G32_SINT
XMINT3 DXGI_FORMAT_R32G32B32_SINT
XMINT4 DXGI_FORMAT_R32G32B32A32_SINT
XMSHORT2 D3DDECLTYPE_SHORT2 D3DFMT_V16U16 DXGI_FORMAT_R16G16_SINT
XMSHORTN2 D3DDECLTYPE_SHORT2N D3DFMT_V16U16 DXGI_FORMAT_R16G16_SNORM
XMSHORT4 D3DDECLTYPE_SHORT4 D3DFMT_x16x16x16x16 DXGI_FORMAT_R16G16B16A16_SINT
XMSHORTN4 D3DDECLTYPE_SHORT4N D3DFMT_x16x16x16x16 DXGI_FORMAT_R16G16B16A16_SNORM
XMUBYTE2 DXGI_FORMAT_R8G8_UINT
XMUBYTEN2 D3DFMT_A8P8, D3DFMT_A8L8 DXGI_FORMAT_R8G8_UNORM
XMUINT2 DXGI_FORMAT_R32G32_UINT
XMUINT3 DXGI_FORMAT_R32G32B32_UINT
XMUINT4 DXGI_FORMAT_R32G32B32A32_UINT
XMU555 D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5 DXGI_FORMAT_B5G5R5A1_UNORM
XMU565 D3DFMT_R5G6B5 DXGI_FORMAT_B5G6R5_UNORM
XMUBYTE4 D3DDECLTYPE_UBYTE4 D3DFMT_x8x8x8x8 DXGI_FORMAT_x8x8x8x8_UINT
XMUBYTEN4 D3DDECLTYPE_UBYTE4N D3DFMT_x8x8x8x8 DXGI_FORMAT_x8x8x8x8_UNORM
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM (XMLoadUDecN4_XRXMStoreUDecN4_XRを使用します)
XMUDEC4 D3DDECLTYPE_UDEC4 (Xbox Only)
D3DDECLTYPE_UDEC3 (Xbox のみ)
D3DFMT_A2R10G10B10
D3DFMT_A2B10G10R10
DXGI_FORMAT_R10G10B10A2_UINT
XMUDECN4 D3DDECLTYPE_UDEC4N (Xbox のみ)
D3DDECLTYPE_UDEC3N (Xbox のみ)
D3DFMT_A2R10G10B10
D3DFMT_A2B10G10R10
DXGI_FORMAT_R10G10B10A2_UNORM
XMUNIBBLE4 D3DFMT_A4R4G4B4, D3DFMT_X4R4G4B4 DXGI_FORMAT_B4G4R4A4_UNORM (DXGI 1.2+)
XMUSHORT2 D3DDECLTYPE_USHORT2 D3DFMT_G16R16 DXGI_FORMAT_R16G16_UINT
XMUSHORTN2 D3DDECLTYPE_USHORT2N D3DFMT_G16R16 DXGI_FORMAT_R16G16_UNORM
XMUSHORT4 D3DDECLTYPE_USHORT4 (Xbox のみ) D3DFMT_x16x16x16x16 DXGI_FORMAT_R16G16B16A16_UINT
XMUSHORTN4 D3DDECLTYPE_USHORT4N D3DFMT_x16x16x16x16 DXGI_FORMAT_R16G16B16A16_UNORM

 

DirectXMath ライブラリのグローバル定数

データ セグメントのサイズを縮小するために、DirectXMath ライブラリは XMGLOBALCONST マクロを使用して、実装でいくつかのグローバル内部定数を活用します。 慣例により、このような内部グローバル定数には g_XMという接頭辞が付けられます。 通常、これらは次のいずれかのタイプです: XMVECTORU32XMVECTORF32、または XMVECTORI32

これらの内部グローバル定数は、DirectXMath ライブラリの将来のリビジョンで変更される可能性があります。 可能な場合は、 g_XM グローバル値を直接使用するのではなく、定数をカプセル化するパブリック関数を使用します。 XMGLOBALCONST を使用して独自のグローバル定数を宣言することもできます。

Windows SSE と SSE2

SSE 命令セットは、単精度浮動小数点ベクトルのみをサポートします。 DirectXMath は、整数ベクトルのサポートを提供するために SSE2 命令セットを使用する必要があります。 SSE2 は、Pentium 4 の導入以降のすべての Intel プロセッサ、すべての AMD K8 以降のプロセッサ、およびすべての x64 対応プロセッサでサポートされています。

Note

Windows 8 for x86 以降では SSE2 のサポートが必要です。 Windows x64 のすべてのバージョンでは SSE2 のサポートが必要です。 ARM / ARM64 上の Windows には ARM_NEON が必要です。

 

ルーチンバリアント

DirectXMath 関数には、作業を容易にするいくつかのバリエーションがあります。

  • より少数のベクトル比較演算に基づいて複雑な条件分岐を作成する比較関数。 これらの関数の名前は、XMVector3InBoundsR のように「R」で終わります。 関数は、比較レコードを UINT 戻り値として、または UINT 出力パラメータとして返します。 値をテストするには、 XMComparision* マクロを使用できます。
  • より大きなベクトル配列に対してバッチ形式の操作を実行するためのバッチ関数。 これらの関数の名前は、 XMVector3TransformStreamのように「Stream」で終わります。 関数は入力の配列に対して動作し、出力の配列を生成します。 通常、入力と出力のストライドを実行します。
  • より遅く、より正確な結果ではなく、より高速な推定を実装する推定関数。 これらの関数の名前は、 XMVector3NormalizeEstのように「Est」で終わります。 推定を使用した場合の品質とパフォーマンスへの影響はプラットフォームによって異なりますが、パフォーマンスが重要なコードには推定バリアントを使用することをお勧めします。

プラットフォームの不一致

DirectXMath ライブラリは、パフォーマンスが重視されるグラフィック アプリケーションやゲームで使用することを目的としています。 したがって、実装は、サポートされているすべてのプラットフォームで通常の処理を実行する際の最適な速度を実現するように設計されています。 境界条件での結果、特に浮動小数点特殊値を生成する結果は、ターゲットごとに異なる可能性があります。 この動作は、Windows 32 ビットの非組み込みターゲットの x87 制御ワードや、Windows 32 ビットと 64 ビットの両方の SSE 制御ワードなど、他の実行時設定にも依存します。 さらに、さまざまな CPU ベンダー間で境界条件が異なります。

数値の正確さが最も重要となる科学アプリケーションやその他のアプリケーションでは DirectXMath を使用しないでください。 また、この制限は、倍精度やその他の拡張精度の計算がサポートされていないことにも反映されています。

Note

_XM_NO_INTRINSICS_ スカラー コード パスは、通常、パフォーマンスではなくコンプライアンスのために記述されます。 境界条件の結果も異なります。

 

プラットフォーム固有の拡張機能

DirectXMath ライブラリは、幅広くサポートされている組み込み命令 (SSE2 および ARM-NEON) を使用して、x86、x64、および Windows RT プラットフォームに優れたサポートを提供し、C++ SIMD プログラミングを簡素化することを目的としています。

ただし、プラットフォーム固有の指示が有益な場合もあります。 DirectXMath の実装方法により、多くの場合、標準コンパイラでサポートされている組み込みステートメントで DirectXMath 型を直接使用したり、拡張命令をサポートしていないプラットフォームのフォールバック パスとして DirectXMath を使用したりすることが簡単になります。

たとえば、SSE 4.1 のドット積命令を活用する簡略化された例を次に示します。 実行時に無効な命令例外が発生しないように、コードパスを明示的に保護する必要があることに注意してください。 コード パスが、分岐の追加コストや複数のコード パスを維持する複雑さなどを正当化するのに十分な作業を実行することを確認します。

#include <Windows.h>
#include <stdio.h>

#include <DirectXMath.h>

#include <intrin.h>
#include <smmintrin.h>

using namespace DirectX;

bool g_bSSE41 = false;

void DetectCPUFeatures()
{
#ifndef _M_ARM
   // See __cpuid documentation for more information

   int CPUInfo[4] = {-1};
#if defined(__clang__) || defined(__GNUC__)
   __cpuid(0, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else
   __cpuid(CPUInfo, 0);
#endif

   if ( CPUInfo[0] >= 1 )
   {
#if defined(__clang__) || defined(__GNUC__)
        __cpuid(1, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
#else
        __cpuid(CPUInfo, 1);
#endif

       if ( CPUInfo[2] & 0x80000 )
           g_bSSE41 = true;
   }
#endif
}

int main()
{
   if ( !XMVerifyCPUSupport() )
       return -1;

   DetectCPUFeatures();

   ...

   XMVECTORF32 v1 = { 1.f, 2.f, 3.f, 4.f };
   XMVECTORF32 v2 = { 5.f, 6.f, 7.f, 8.f };

   XMVECTOR r2, r3, r4;

   if ( g_bSSE41 )
   {
#ifndef _M_ARM
       r2 = _mm_dp_ps( v1, v2, 0x3f );
       r3 = _mm_dp_ps( v1, v2, 0x7f );
       r4 = _mm_dp_ps( v1, v2, 0xff );
#endif
   }
   else
   {
       r2 = XMVector2Dot( v1, v2 );
       r3 = XMVector3Dot( v1, v2 );
       r4 = XMVector4Dot( v1, v2 );
   }

   ...

   return 0;
}

プラットフォーム固有の拡張機能の詳細については、以下を参照してください。

DirectXMath: SSE、 SSE2 および ARM-NEON
DirectXMath: SSE3 と SSSE3
DirectXMath: SSE4.1 および SSE4.2
DirectXMath: AVX
DirectXMath: F16C と FMA
DirectXMath: AVX2
DirectXMath: ARM64

DirectXMath プログラミング ガイド