movaps xmm2,xmmword ptr [rax]
movups xmm5,xmmword ptr [rax+20h]
movups xmm4,xmmword ptr [rax+10h]
Da soll eigentlich eine Matrix geladen werden. Wie Visual C++ 2013 darauf kommt, dass die ersten vier
floats 16-Byte-ausgerichtet sind, und die anderen acht nicht? Keine Ahnung. Warum das einen Unterschied machen sollte? Keine Ahnung, denn moderne CPUs können beides gleich schnell. Jedenfalls ist die Matrix
nicht ausgerichtet und nun stürzt meine Release-Version ab wenn man auf 3rd Person schaltet.
Dieser Fehler sieht so ähnlich aus und sollte eigentlich schon behoben sein. Aber wie ich Visual C++ kenne, muss man ihn für jeden Datentyp einzeln beheben lassen.
Nachtrag: Problematisch ist der folgende Quelltext:
Code: Alles auswählen
Math::RigidMotion<float, 3> const planeToView = {
quaternionFromPolarViewer(myViewersRotationX, myViewersRotationY) * myF22.rotation,
Math::vectorFromXYZ(0.0f, 0.0f, 12.0f)
};
myRasterizer.rasterizeFlatShadedLineSegment(
transformed(gearOriginF_local, similarityFrom(planeToView)),
transformed(frontGearEnd, similarityFrom(planeToView)),
8
);
myRasterizer.rasterizeFlatShadedLineSegment(
transformed(gearOriginR_local, similarityFrom(planeToView)),
transformed(rightGearEnd, similarityFrom(planeToView)),
8
);
myRasterizer.rasterizeFlatShadedLineSegment(
transformed(gearOriginL_local, similarityFrom(planeToView)),
transformed(leftGearEnd, similarityFrom(planeToView)),
8
);
myRasterizer.rasterizeFlatShadedLineSegment(
transformed(Math::pointFromXYZ(0.75f, -0.08f, 0.35f), similarityFrom(planeToView)),
transformed(Math::pointFromXYZ(0.0f, 0.f, +0.f), similarityFrom(planeToView)),
8
);
Im Speziellen werden die acht identischen(!!!) Aufrufe
similarityFrom(planeToView), die Quaternion & Offset in eine 3×4-Matrix umwandeln, nicht wegoptimiert(!!!!!!!!). Einer davon wird dann via
movaps geladen obwohl er nicht an 16 B ausgerichtet auf dem Stapel liegt, und … bumm.
Wenn man es wie 1987 macht und eine temporäre Variable anlegt:
Code: Alles auswählen
Math::RigidMotion<float, 3> const planeToView = {
quaternionFromPolarViewer(myViewersRotationX, myViewersRotationY) * myF22.rotation,
Math::vectorFromXYZ(0.0f, 0.0f, 12.0f)
};
auto const planeToViewSimilarity = similarityFrom(planeToView);
myRasterizer.rasterizeFlatShadedLineSegment(
transformed(gearOriginF_local, planeToViewSimilarity),
transformed(frontGearEnd, planeToViewSimilarity),
8
);
myRasterizer.rasterizeFlatShadedLineSegment(
transformed(gearOriginR_local, planeToViewSimilarity),
transformed(rightGearEnd, planeToViewSimilarity),
8
);
myRasterizer.rasterizeFlatShadedLineSegment(
transformed(gearOriginL_local, planeToViewSimilarity),
transformed(leftGearEnd, planeToViewSimilarity),
8
);
myRasterizer.rasterizeFlatShadedLineSegment(
transformed(Math::pointFromXYZ(0.75f, -0.08f, 0.35f), planeToViewSimilarity),
transformed(Math::pointFromXYZ(0.0f, 0.f, +0.f), planeToViewSimilarity),
8
);
dann funktioniert es nicht nur, sondern resultiert in weniger als halb so vielen Maschinenbefehlen.
Visual C++ 2013 Update 3 für x64 mit /O2.
Prost.