Der Großteil des Hochleistungscodes in modernen Konsolenspielen basiert auf einer Art Mittelweg zwischen Assembly und C ++: Compiler-Eigenheiten . Diese Konstrukte sehen aus und analysieren sie wie C ++ - Funktionen, werden jedoch tatsächlich in Einzelmaschinenanweisungen übersetzt . So sieht beispielsweise meine Funktion "Klemme jeden Wert des Vektors V auf> = a und <= b" aus
// for each v.x, ensure v.x >= a.x && v.x <= b.x
inline __m128 ClampSIMD( const __m128 &v, const __m128 & a, const __m128 & b )
{
return _mm_max_ps( a, _mm_min_ps( v, b ) );
}
Bei Funktionen wie diesen denke ich immer noch an die spezifischen Maschinenanweisungen , aber ich habe die Möglichkeit, sie in C zu schreiben, damit ich mich nicht um das Ausmalen und Planen von Registern und das Laden von Operationen und anderen langweiligen Details kümmern muss.
Sie müssen sich immer noch darüber im Klaren sein, welche Anweisungen die CPU unterstützt, insbesondere weil moderne Compiler Code schlecht vektorisieren können, verglichen mit der Leistungsfähigkeit eines intelligenten Menschen. Manchmal können auch subtile Details, wie Sie Ihren Code anordnen , enorme Auswirkungen auf die Leistung haben , die nicht offensichtlich sind, ohne zu verstehen, was der Computer tut.
Obwohl wir in der Assembly möglicherweise nicht programmieren, debuggen wir in der Assembly noch häufig. Durch die Optimierung von Compilern wird Code aggressiv in einer Weise reorganisiert, mit der Debugger nicht Schritt halten können. Beim Debuggen eines Builds im "Release-Modus" empfiehlt es sich daher, den Disassembler zu öffnen und den Code auf diese Weise zu durchsuchen. Dieser GDC-Vortrag zum "Forensic Debugging" von Abstürzen zeigt viele der Gründe und Gründe für das Debuggen auf dieser Ebene.