DirectX :: XMMATRIX Неверное умножение после передачи функции (C ++) - PullRequest
0 голосов
/ 08 мая 2019

Мне трудно понять, почему я получаю разные результаты при умножении двух матриц DirectX 4x4 вместе, в зависимости от того, выполняется ли умножение внутри функции класса или нет.

Используя в качестве примера единичные матрицы, значения result1 и result2 в конечном итоге будут разными, используя следующий код.

#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;
    }

Это действительно похоже на результат2, ожидаемый результат начинается в строке 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

Я знаю, передавая массив как функцию, я делаю его копию, но я бы не подумал, что здесь что-то изменится.

Любая помощь будет принята с благодарностью!

1 Ответ

2 голосов
/ 09 мая 2019

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.

...