【问题标题】:DirectXMathConvert.inl assertion failure (DirectXMathConvert.inl line 704)DirectXMathConvert.inl 断言失败(DirectXMathConvert.inl 第 704 行)
【发布时间】:2015-08-17 08:51:47
【问题描述】:

有人能帮我把这段代码翻译成人类可读的吗?

|704| assert(((uintptr_t)pSource & 0xF) == 0);

基本上这个断言在我的程序中失败,但不是 100% 的时间(没有我重新编译任何东西),这很奇怪。

完整的XMLoadFloat4A 函数是(第 697 行 - DirectXMathConvert.inl):

|697| _Use_decl_annotations_
|698| inline XMVECTOR XM_CALLCONV XMLoadFloat4A
|699| (
|700|     const XMFLOAT4A* pSource
|701| )
|702| {
|703|     assert(pSource);
|704|     assert(((uintptr_t)pSource & 0xF) == 0);
|705| #if defined(_XM_NO_INTRINSICS_)
|706|     XMVECTOR V;
|707|     V.vector4_f32[0] = pSource->x;
|708|     V.vector4_f32[1] = pSource->y;
|709|     V.vector4_f32[2] = pSource->z;
|710|     V.vector4_f32[3] = pSource->w;
|711|     return V;
|712| #elif defined(_XM_ARM_NEON_INTRINSICS_)
|713|     return vld1q_f32_ex( reinterpret_cast<const float*>(pSource), 128 );
|714| #elif defined(_XM_SSE_INTRINSICS_)
|715|     return _mm_load_ps( &pSource->x );
|716| #endif
|717| }

用例:

// Convert an XMFLOAT4A to XMVECTOR
XMVECTOR getXMVECTORfromXMFLOAT4A(const XMFLOAT4A& v) {
    return XMLoadFloat4A(&v);
}
XMVECTOR foo = getXMVECTORfromXMFLOAT4A(XMFLOAT4A(1.0, 2.0, 3.0, 1.0));

// Transform XMFLOAT4A with XMMATRIX
XMFLOAT4A XMFloat4Transform(const XMFLOAT4A& v, const XMMATRIX& m) {
    XMVECTOR vec = XMLoadFloat4A(&v);
    XMVECTOR rot = XMVector4Transform(vec, m);
    XMFLOAT4A result;
    XMStoreFloat4A(&result, rot);
    return result;
}
XMMATRIX m = XMMatrixLookAtLH(...);
XMFLOAT4A foo (1.0, 2.0, 3.0, 1.0);
XMFLOAT4A bar = XMFloat4Transform(foo, m);

为什么这个断言失败了?为什么不是 100% 的时间?

【问题讨论】:

  • 哪个版本的 MSVC?
  • 您可能想查看 DirectX Tool Kit 中 DirectXMath 的 SimpleMath 包装器。它使 DirectXMath 对此类内容更加宽容。

标签: visual-c++ assert directxmath


【解决方案1】:

正如MSDN 所说的XMFLOAT4A“描述了一个在 16 字节边界上对齐的 XMFLOAT4 结构。”

这就是assert 正在检查的内容。 XMLoadFloat4A 有一个 XMFLOAT4 是不够的,它只需要为 ist 浮点成员(8 个字节)对齐,它需要一个在 16 字节边界上对齐的 XMFLOAT4A。这可能是出于性能原因或因为内在函数需要它。

通常XMFLOAT4A 标记为__declspec(align(16)),因此编译器知道他必须将此结构对齐到16 个字节。在您的情况下,您可以检查XMFLOAT4A 的声明。我建议使用compiler switch /EP,它在预处理器阶段之后和编译器启动之前写出一个文件。这可能会帮助您检测某些宏是否与您的 XMFLOAT4A 声明混淆。

您还应该检查哪个确切的调用失败了。

另外:MSDN 有一个article on __declspec(align(#))。这表示如果您将 XMFLOAT4A 按值传递给函数,那么您将失去对齐。在您的代码中,我只看到通过引用传递,但这仍然是一个需要记住的有趣点。

【讨论】:

  • 我怎样才能确保我的XMFLOAT4A 总是对齐呢? Doc说应该是,但断言仍然失败。不妨将我所有的XMFLOAT4A 转换为XMFLOAT4
  • XMFLOAT4A 声明是 __declspec(align(16)) struct XMFLOAT4A : public XMFLOAT4 {...} - 我在预处理器文件的其他任何地方都看不到任何与它有关的东西。改用XMFLOAT4 我猜=)
  • @PinkTurtle 我在答案中添加了一些 cmets。也许你想检查一下。
  • 是的,我仔细检查了我所有的 XMFLOAT4A 都是通过引用传递的。实际上,编译器会拒绝为“通过复制”XMFLOAT4A 参数进行编译。我选择了普通的 XMFLOAT4。
  • 编译器将允许您在为 x64 构建时“通过复制”16 字节对齐的数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-12
  • 1970-01-01
  • 1970-01-01
  • 2023-01-24
  • 2021-06-18
相关资源
最近更新 更多