I am having some trouble understanding why I am getting different results when multiplying two DirectX 4x4 matrices together, depending on whether the multiplication is performed within a class function or not.
Using identity matrices as an example, the values of result1 and result2 end up being different using the following code.
#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;
}
It actually looks like in result2, the expected result starts in row 3 of the matrix? (Output below)
//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
I know through passing the array as a function I am making a copy of it, but I wouldn't have thought that would make a difference here.
Any help would be greatly appreciated!
TL;DR: This is a compiler bug likely due to bad code-generation.
The weird output happens only when using the x86 (32-bit) compiler, not when using the x64 (64-bit) native compiler. I tried a few different ways of outputting the results, and they are consistently weird for x86 but correct for x64.
It seems to happen in both Debug and Release (optimized) configurations, and with both /fp:fast
and /fp:precise
.
This does not happen with x64 native code or with x86 if you use /arch:IA32
.
I'm able to reproduce the same issue with VS 2017 (15.9.11) as well as 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;
}
You should use Help -> Send Feedback -> Report a Problem... to report the bug. Be sure to mention it applies to both VS 2017 and VS 2019.