Games for Windows and the DirectX SDK blog

Technical tips, tricks, and news about game development for Microsoft platforms including desktop, Xbox, and UWP


Project maintained by walbourn Hosted on GitHub Pages — Theme by mattgraham
Home | Posts by Tag | Posts by Month

Known Issues - DirectXMath 3.06

directxmath

Originally posted to Chuck Walbourn's Blog on MSDN,

The Windows 8.1 SDK includes DirectXMath version 3.06 for use with Windows Store apps and Win32 desktop applications on Windows 8.x, Windows RT, Windows 7, and Windows Vista. DirectXMath 3.06 is also part of the Windows phone 8.1 SDK for use on Windows phone 8.x. There are a number of minor bugs in the library that have been reported by customers since it was released, which will be addressed in future SDK releases. In the meantime, since the code is all inline in the headers, you can make the fix directly to a local copy as needed or work around the issue in your own code.

BoundingBox::Contains

The triangle/oriented box/frustum in axis-aligned tests often return INTERSECTS when they should return CONTAINS. The fix is in DirectXCollision.inl change XMVector3LengthSq to XMVectorAbs in 3 places for the triangle in axis-aligned box test (lines 1293, 1296, and 1299), once in the oriented box in axis-aligned test (line 1409), and once in the frustum in axis-aligned box test (line 1437).

XMVectorRound

The rounding function works fine unless the number has a magnitude larger than 8388608 (or is a floating-point special) in which case it returns the wrong result. The fix is to put a new version of the function into DirectXMathVector.inl starting on line 2353:

inline XMVECTOR XM_CALLCONV XMVectorRound
(
    FXMVECTOR V
)
{
#if defined(_XM_NO_INTRINSICS_)

    XMVECTOR vResult = {
    Internal::round_to_nearest(V.vector4_f32[0]),
    Internal::round_to_nearest(V.vector4_f32[1]),
    Internal::round_to_nearest(V.vector4_f32[2]),
    Internal::round_to_nearest(V.vector4_f32[3])
    };
    return vResult;

#elif defined(_XM_ARM_NEON_INTRINSICS_)
    uint32x4_t sign = vandq_u32(V, g_XMNegativeZero);
    uint32x4_t sMagic = vorrq_u32(g_XMNoFraction, sign);
    float32x4_t R1 = vaddq_f32(V, sMagic);
    R1 = vsubq_f32(R1, sMagic);
    float32x4_t R2 = vabsq_f32(V);
    uint32x4_t mask = vcleq_f32(R2, g_XMNoFraction);
    XMVECTOR vResult = vbslq_f32(mask, R1, V);
    return vResult;
#elif defined(_XM_SSE_INTRINSICS_)
    __m128 sign = _mm_and_ps(V, g_XMNegativeZero);
    __m128 sMagic = _mm_or_ps(g_XMNoFraction, sign);
    __m128 R1 = _mm_add_ps(V, sMagic);
    R1 = _mm_sub_ps(R1, sMagic);
    __m128 R2 = _mm_and_ps(V, g_XMAbsMask);
    __m128 mask = _mm_cmple_ps(R2, g_XMNoFraction);
    R2 = _mm_andnot_ps(mask, V);
    R1 = _mm_and_ps(R1, mask);
    XMVECTOR vResult = _mm_xor_ps(R1, R2);
    return vResult;
#endif
}

Thanks to Bruce Dawson for the report and fix. This issue does not affect the SSE4 version of XMVectorRound from this post.

XMVectorATan2, XMVectorATan2Est

This is a really subtle bug with a specific special-case of X == INF, Y is finite < 0. It was returning +0 instead of -0. The fix is in DirectXMathVector.inl on lines 5148 and 5790 change:

R1 = XMVectorSelect( Pi, Zero, XIsPositive );

->

R1 = XMVectorSelect( Pi, g_XMNegativeZero, XIsPositive );

XMStoreFloat3SE

While DirectXMath 3.06 did fix this format, there was still a subtle bug in it. The fix is in DirectXPackedVector.inl line 1771, change:

fi.i &= 0xFF800000; // cut off fraction

->

fi.i += 0x00004000; // round up leaving 9 bits in fraction (including assumed 1)

Related: Known Issues: DirectXMath 3.03, DirectXMath 3.06

Note: Attached are the relevant files with these fixes applied. It requires you use the rest of the library in the Windows 8.1 SDK or the Windows phone 8.1 SDK, and the code is subject to the respective SDK’s license agreement.

Update: These fixes all shipped in DirectXMath 3.07.

GitHub: Note that DirectXMath is now hosted on GitHub.

DirectXMath_306_hotfixes.zip