【问题标题】:DirectX::XMMATRIX Multiplication incorrect after function pass (C++)函数传递后 DirectX::XMMATRIX 乘法不正确 (C++)
【发布时间】:2019-05-08 11:21:06
【问题描述】:

我很难理解为什么将两个 DirectX 4x4 矩阵相乘时得到不同的结果,具体取决于乘法是否在类函数中执行。

以恒等矩阵为例,使用以下代码,结果 1 和结果 2 的值最终会有所不同。

#include <iostream>
#include <DirectXMath.h>

using namespace DirectX;

class Model {
public:
    XMMATRIX MatrixMult(XMMATRIX test) {
        XMMATRIX result = test * XMMatrixIdentity();
        return result;
    }
private:
};

int main() {

    Model m;

    XMMATRIX result1 = XMMatrixIdentity() * XMMatrixIdentity(); //returns identity
    XMMATRIX result2 = m.MatrixMult(XMMatrixIdentity()); //doesn't return identity
    int height = 4;
    int width = 4;

    //Output results
    XMMATRIX results[2] = { result1, result2 };

    //for each result
    for (int res = 0; res < 2; ++res) {
        //for each row
        for (int i = 0; i < height; ++i)
        {
            //for each column
            for (int j = 0; j < width; ++j)
            {
                if (j == 0) {
                    std::cout << XMVectorGetX(results[res].r[i]) << ' ';
                }
                else if (j == 1) {
                    std::cout << XMVectorGetY(results[res].r[i]) << ' ';
                }
                else if (j == 2) {
                    std::cout << XMVectorGetZ(results[res].r[i]) << ' ';
                }
                else if (j == 3) {
                    std::cout << XMVectorGetW(results[res].r[i]) << ' ';
                }
            }
            std::cout << std::endl;
        }
        std::cout << "\n";
    }

    return 0;
    }

实际上看起来像在 result2 中,预期的结果从矩阵的第 3 行开始? (下面的输出)

//result1
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

//result2
8.2597e-39 -1.07374e+08 -1.07374e+08 -1.07374e+08
-1.07374e+08 -1.07374e+08 -1.07374e+08 -1.07374e+08
1 0 0 0
0 1 0 0

我知道通过将数组作为函数传递,我正在复制它,但我没想到这会有所作为。

任何帮助将不胜感激!

【问题讨论】:

  • 你使用什么编译器和更新?
  • 我正在使用 Visual Studio Community 2017 (15.9.11)
  • 您如何看待结果?如果我使用printf%f,它会输出合理的输出。
  • 嗯,这很奇怪。我已经包含了用于输出结果的代码,但是在调试时我在局部变量表中看到了相同的值(所以会认为它与输出过程无关?)。
  • 一般输出XMMATRIX的最佳方式是使用XMStoreFloat4x4,然后使用XMFLOAT4X4结构打印出元素。很可能存在一个编译器错误,所有 SIMD 都在内存中,并且你正在做的来回......

标签: c++ matrix directx multiplication directxmath


【解决方案1】:

TL;DR:这是一个编译器错误,可能是由于错误的代码生成。

只有在使用 x86(32 位)编译器时才会出现奇怪的输出,而不是在使用 x64(64 位)本机编译器时。我尝试了几种不同的输出结果的方法,它们对于 x86 来说一直很奇怪,但对于 x64 来说是正确的。

  • 这似乎发生在调试和发布(优化)配置以及/fp:fast/fp:precise 中。

  • 不会发生在 x64 本机代码或 x86(如果您使用 /arch:IA32)。

  • 我能够在 VS 2017 (15.9.11) 和 VS 2019 (16.0.3) 中重现相同的问题。

#include <iostream>
#include <stdio.h>
#include <DirectXMath.h>

using namespace DirectX;

class Model {
public:
    XMMATRIX MatrixMult(XMMATRIX test) {
        XMMATRIX result = test * XMMatrixIdentity();
        return result;
    }
private:
};

int main() {

    Model m;

    XMMATRIX result1 = XMMatrixIdentity() * XMMatrixIdentity(); //returns identity
    XMMATRIX result2 = m.MatrixMult(XMMatrixIdentity()); //doesn't return identity
    int height = 4;
    int width = 4;

    //Output results
#if 0
    XMFLOAT4X4 mat[2];
    XMStoreFloat4x4(&mat[0], result1);
    XMStoreFloat4x4(&mat[1], result2);

    //for each result
    for (int res = 0; res < 2; ++res) {
        //for each row
        for (int i = 0; i < height; ++i)
        {
            printf("%f %f %f %f\n",
                mat[res].m[i][0], mat[res].m[i][1], mat[res].m[i][2], mat[res].m[i][3]);
        }
    }
#elif 0
    XMFLOAT4X4 mat[2];
    XMStoreFloat4x4(&mat[0], result1);
    XMStoreFloat4x4(&mat[1], result2);

    //for each result
    for (int res = 0; res < 2; ++res) {
        //for each row
        for (int i = 0; i < height; ++i)
        {
            //for each column
            for (int j = 0; j < width; ++j)
            {
                std::cout << mat[res].m[i][j] << ' ';
            }
            std::cout << std::endl;
        }
        std::cout << "\n";
    }
#else
    XMMATRIX results[2] = { result1, result2 };

    //for each result
    for (int res = 0; res < 2; ++res) {
        //for each row
        for (int i = 0; i < height; ++i)
        {
            //for each column
            for (int j = 0; j < width; ++j)
            {
                if (j == 0) {
                    std::cout << XMVectorGetX(results[res].r[i]) << ' ';
                }
                else if (j == 1) {
                    std::cout << XMVectorGetY(results[res].r[i]) << ' ';
                }
                else if (j == 2) {
                    std::cout << XMVectorGetZ(results[res].r[i]) << ' ';
                }
                else if (j == 3) {
                    std::cout << XMVectorGetW(results[res].r[i]) << ' ';
                }
            }
            std::cout << std::endl;
        }
        std::cout << "\n";
    }
#endif

    return 0;
    }

您应该使用帮助 -> 发送反馈 -> 报告问题... 来报告错误。请务必提及它适用于 VS 2017 和 VS 2019。

【讨论】:

  • 是的,已经解决了,感谢您花时间解决这个问题!我已通过您建议的流程报告了该错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-27
  • 2023-03-06
  • 2021-02-05
  • 2015-01-02
相关资源
最近更新 更多