使用如下函数
FLOAT XMConvertHalfToFloat(HALF Value);
FLOAT* XMConvertHalfToFloatStream(_Out_bytecap_x_(sizeof(FLOAT)+OutputStride*(HalfCount-1)) FLOAT* pOutputStream,
_In_ UINT OutputStride,
_In_bytecount_x_(sizeof(HALF)+InputStride*(HalfCount-1)) CONST HALF* pInputStream,
_In_ UINT InputStride, _In_ UINT HalfCount);
HALF XMConvertFloatToHalf(FLOAT Value);
HALF* XMConvertFloatToHalfStream(_Out_bytecap_x_(sizeof(HALF)+OutputStride*(FloatCount-1)) HALF* pOutputStream,
_In_ UINT OutputStride,
_In_bytecount_x_(sizeof(FLOAT)+InputStride*(FloatCount-1)) CONST FLOAT* pInputStream,
_In_ UINT InputStride, _In_ UINT FloatCount);
HALF类型的定义如下
// 16 bit floating point number consisting of a sign bit, a 5 bit biased
// exponent, and a 10 bit mantissa
//typedef WORD HALF;
typedef USHORT HALF;
包含的文件如下,二选一即可
#include <xnamath.h>
#include <DirectXPackedVector.h>
函数体的内容在文件DirectXPackedVector.inl中
inline float XMConvertHalfToFloat
(
HALF Value
)
{
#if defined(_XM_F16C_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
__m128i V1 = _mm_cvtsi32_si128( static_cast<int>(Value) );
__m128 V2 = _mm_cvtph_ps( V1 );
return _mm_cvtss_f32( V2 );
#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || __aarch64__) && !defined(_XM_NO_INTRINSICS_)
uint16x4_t vHalf = vdup_n_u16(Value);
float32x4_t vFloat = vcvt_f32_f16(vreinterpret_f16_u16(vHalf));
return vgetq_lane_f32(vFloat, 0);
#else
auto Mantissa = static_cast<uint32_t>(Value & 0x03FF);
uint32_t Exponent = (Value & 0x7C00);
if ( Exponent == 0x7C00 ) // INF/NAN
{
Exponent = 0x8f;
}
else if (Exponent != 0) // The value is normalized
{
Exponent = static_cast<uint32_t>((static_cast<int>(Value) >> 10) & 0x1F);
}
else if (Mantissa != 0) // The value is denormalized
{
// Normalize the value in the resulting float
Exponent = 1;
do
{
Exponent--;
Mantissa <<= 1;
} while ((Mantissa & 0x0400) == 0);
Mantissa &= 0x03FF;
}
else // The value is zero
{
Exponent = static_cast<uint32_t>(-112);
}
uint32_t Result =
((static_cast<uint32_t>(Value) & 0x8000) << 16) // Sign
| ((Exponent + 112) << 23) // Exponent
| (Mantissa << 13); // Mantissa
return reinterpret_cast<float*>(&Result)[0];
#endif // !_XM_F16C_INTRINSICS_
}
数据类型的转换规则可参考如下链接:
Floating-point rules (Direct3D 11) - Win32 apps | Microsoft Docs