I'm new to DirectX11 and I'm trying to adapt a file written using DirectX Legacy to new DirectX but I'm having some trouble with template XMVectorPermute, which used to be a function in Legacy file.
I'm trying to make compiler recognize the template in DirectXMath.h
:
// General permute template
template<uint32_t PermuteX, uint32_t PermuteY, uint32_t PermuteZ, uint32_t PermuteW>
inline XMVECTOR XM_CALLCONV XMVectorPermute(FXMVECTOR V1, FXMVECTOR V2)
{
//...Definition
by using the following code:
template DirectX::XMVECTOR DirectX::XMVectorPermute<PermuteXXY.i[0], PermuteXXY.i[1], PermuteXXY.i[2], PermuteXXY.i[3]>(FXMVECTOR V1, FXMVECTOR V2);
in which PermuteXXY
is defined as:
static CONST DirectX::XMVECTORI32 PermuteXXY =
{
DirectX::XM_PERMUTE_0X, DirectX::XM_PERMUTE_0X, DirectX::XM_PERMUTE_0Y, DirectX::XM_PERMUTE_0W
};
but the compiler or the linker cannot make a match: Error reported
XM_PERMUTE_...
is defined as a const uint32_t
in DirectXMath.h
, and XMVECTORI32
is defined as a union:
union
{
int32_t i[4];
XMVECTOR v;
};
I'm not very good at c++ template so please help me with this as thoroughly as possible. Thanks a lot!
There are a couple of issues here that are causing your code to fail.
First, you cannot use a member of an XMVECTORI32
to provide a template parameter to XMVectorPermute
. This is not because of the type difference (same thing happens with XMVECTORU32
). I believe the issue is because the array i
is not declared as const
, and the value must be constant to be used as a template parameter. In any case, VS2017 refuses to compile the code.
Second, you cannot specialize a template function without providing a body for that function. This would mean your second line is incomplete, and would need to have an implementation written by you in order to compile.
This doesn't mean you're SOL though, just that you need to change your approach. If the template parameters are always constant (and it looks like they should be, in your code), you can define a function that takes the two vector parameters and specifies the exact permute constants to use for that particular operation.
The following code is an example of this:
DirectX::XMVECTOR XMVectorPermuteXXY(DirectX::FXMVECTOR V1, DirectX::FXMVECTOR V2)
{
return DirectX::XMVectorPermute<DirectX::XM_PERMUTE_0X,
DirectX::XM_PERMUTE_0X,
DirectX::XM_PERMUTE_0Y,
DirectX::XM_PERMUTE_0W>(V1, V2);
}
Any other operations that need to be specified (XYXY, ZZWW, YYWZ, etc.) can be defined in a similar manner, with wrapper functions that specify the proper template parameters.
A second option is to use the non-template version of XMVectorPermute
, that takes two vectors and four permute constants. This version will likely be a bit slower, but will allow you to specify the permute constants at run time.
That code looks like this:
XMVECTOR XMVectorPermuteXXY(FXMVECTOR V1, FXMVECTOR V2)
{
return XMVectorPermute(V1, V2,
XM_PERMUTE_0X,
XM_PERMUTE_0X,
XM_PERMUTE_0Y,
XM_PERMUTE_0W);
}
Based on the code you're migrating, you'll need to decide which version you plan on using.