1장 벡터 대수
(벡터의 수학적 내용보다는 DirectXMath 라이브러리의 위주로 작성.)
DirectXMath 라이브러리
- Windows8 이상에서 Direct3D 응용 프로그램을 위한 표준적인 3차원 수학 라이브러리이며 Window SDK의 일부로 포함됨
- SSE2(Streaming SIMD Extensions 2) 명령 집합을 활용.
- SIMD 명령들은 128비트 너비의 SIMD(single instruction multiple data) 레지스터들을 이용해서 32비트 float 또는 int 4개를 하나의 명령으로 처리
- X86에서 SSE2 명령을 사용하기 위해서는 별도 옵션 지정 필요.
- 사용하는 벡터의 형식은 XMVECTOR와 XMFLOAT2,3,4 가 있다.
DirectXMath에서 벡터 자료형
DirectXMath 에서 벡터를 다루는 자료형은 XMVECTOR와 XMFLOAT2, XMFLOAT3, XMFLOAT4 존재.
XMVECTOR
- SIMD 하드웨어 레지스터에 대응되는 벡터 타입으로 XMVECTOR 간의 연산은 하드웨어에서 단일 연산으로 처리됨.
typedef __m128 XMVECTOR;
- 2차원 3차원 벡터의 경우도 128비트 XMVECTOR를 사용하면 SIMD의 장점 사용 가능
- 2차원 3차원 벡터에서 사용하지 않는 성분은 0으로 설정
- XMVECTOR 간의 연산은 하드웨어에서 단일 연산으로 처리됨
- 16바이트 단위로 Alignment 되기 때문에 클래스나 구조체의 멤버변수의 타입으로 사용되는 것은 권장되지 않는다.
- 멤버 변수에 저장할 때는 아래의 XMFLOATn 타입을 사용
- Alignment 에대한 설명은 해당 게시글을 참고.
XMFLOAT2, XMFLOAT3, XMFLOAT4
- 각각 2,3,4개의 float으로 구성되어 있는 구조체로 XMVECTOR를 클래스나 구조체의 멤버로 저장할 때 변환하여 사용
- 연산을 할때는 XMVECTOR로 변환해야 SIMD 하드웨어 지원을 받음.
XMVECTOR와 XMFLOAT- 타입 간의 변환 함수
- XMVECTOR와 XMFLOATn 타입 간에는 변환이 가능하며 Window SDK의 DirectXMathConvert.inl에 관련 함수들 존재
XMVECTOR의 값 Set / Get 함수
- XMVECTOR의 전체값 혹은 특정 값만 설정하거나 읽을 수 있으며 Window SDK의 DirectXMathVector.inl에 관련 함수들 존재
상수 벡터
- 상수 XMVECTOR 인스턴스에는 반드시 XMVECTORF32 형식 또는 XMVECTORU32을 사용해야 한다.
- XMVECTORF32: 실수 형식
- XMVECTORU32: 정수 형식
- 예시
XMGLOBALCONST XMVECTORF32 g_XMOne = { { { 1.0f, 1.0f, 1.0f, 1.0f } } }; XMGLOBALCONST XMVECTORU32 g_XMMaskY = { { { 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000 } } };
함수 호출 규칙
XMVECTOR 인스턴스를 인수로 해서 함수를 호출할 때, 효율성을 위해서는 XMVECTOR 값이 스택이 아니라 SSE/SSE2 레지스터를 통해서 함수에 전달되게 해야 한다. 그런 식으로 전달할 수 있는 인수의 개수는 플랫폼과 컴파일러에 따라 다르다. 플랫폼/컴파일러 의존성을 없애기 위해서 몇 가지 규칙이 존재.
XM_CALLCONV
- SSE/SSE2 레지스터 활용을 위한 호출 규약 역시 컴파일러에 따라 다를 수 있다.
- 컴파일러 의존성을 없애려면 함수 이름 앞에 반드시 XM_CALLCONV 라는 호출 규약 지시자(매크로)를 붙여야 한다.
XMVECTOR 매개변수의 전달에 관한 규칙
- 처음 세 XMVECTOR 매개변수에는 반드시 FXMVECTOR 형식을 지정해야한다.
- 넷째 XMVECTOR 매개변수에는 반드시 GXMVECTOR 형식을 지정해야 한다.
- 다섯째와 여섯째 XMVECTOR 매개변수에는 반드시 HXMVECTOR 형식을 지정해야 한다.
- 그 이상의 XMVECTOR 매개변수들에는 반드시 CXMVECTOR 형식을 지정해야 한다.
- XMVECTOR 매개변수들 사이에 XMVECTOR가 아닌 매개변수가 끼어 있을 경우 XMVECTOR 매개 변수들만 세어서 규칙을 적용한다.
예시
- XM_CALLCONV와 XMVECTOR 규칙을 적용한 예시. (DirectXMath 라이브러리의 코드 중 일부)
XMMATRIX XM_CALLCONV XMMatrixTransformation(
FXMVECTOR ScalingOrigin,
FXMVECTOR ScalingOrientationQuaternion,
FXMVECTOR Scaling,
GXMVECTOR RotationOrigin,
HXMVECTOR RotationQuaternion,
HXMVECTOR Translation) noexcept
생성자의 호출 규칙
생성자는 일반 함수들과 다른 규칙이 적용됨
- 처음 세 XMVECTOR 매개변수에는 FXMVECTOR를 사용
- 나머지에는 CXMVECTOR를 사용
- XM_CALLCONV 호출 규약 지시자를 사용하지 않음
(참고) 위 규칙으로 플랫폼/컴파일 의존성이 제거되는 이유
FXMVECTOR, GXMVECTOR, HXMVECTOR, CXMVECTOR는 각 플랫폼과 컴파일러의 상황에 맞게 타입이 정의되어서 사용된다. 예를 들어 32비트 Windows에서 __fastcall 호출 규약을 지원하는 컴파일러와 __vectorcall 호출 규약을 지원하는 컴파일러는 이 형식들을 다음과 같이 정의.
//__fastcall은 처음 세 XMVECTOR 인수를 레지스터들을 통해서 전달. 나머지는 스택을 사용
typedef const XMVECTOR FXMVECTOR; // 1, 2, 3
typedef const XMVECTOR& GXMVECTOR; // 4
typedef const XMVECTOR& HXMVECTOR; // 5, 6
typedef const XMVECTOR& CXMVECTOR; // 그 이상
// __vectorcall은 처음 여섯 XMVECTOR 인수를 레지스터들을 통해서 전달하고, 나머지는 스택을 사용
typedef const XMVECTOR FXMVECTOR; // 1, 2, 3
typedef const XMVECTOR GXMVECTOR; // 4
typedef const XMVECTOR HXMVECTOR; // 5, 6
typedef const XMVECTOR& CXMVECTOR; // 그 이상
출처:
한빛미디어 출판 <DirectX 12를 이용한 3D 게임 프로그래밍 입문>