Mein Fragment-Shader wurde durch eine kürzliche Änderung erheblich verlangsamt, und ich habe versucht zu verstehen, warum.
Ich habe die Hauptverlangsamung auf den Zugriff auf einen einzelnen einheitlichen Schwimmer isoliert. Wenn ich diese Zeile einbinde:
float not_used = my_uniform;
dann läuft der Shader mehr als doppelt so langsam wie ohne diese Zeile. Der not_used
Float wird nie wieder referenziert.
Warum sollte das passieren? Ich hoffe, es zu verstehen, damit ich versuchen kann, eine schnellere Lösung zu finden.
Ich führe dies auf einem Mac mit Intel HD Graphics 3000 aus. Ich messe die Leistung, indem ich OpenGL-Zeitstempelabfragen vor und nach der Ausführung meiner glDraw
Anrufe durchführe und die ms-Intervalle betrachte. Ich kann weitere Spezifikationen / Details angeben, wenn dies bei der Diagnose des Problems hilfreich wäre.
quelle
glFinish()
oder Ihre Pufferaustauschfunktionen aufrufen , damit der Code tatsächlich ausgeführt wird. Auch ein anständiger glsl-Compiler sollte alle nicht verwendeten Uniformen aus Ihrem Code entfernen.gl{Begin,End}Query
mitGL_TIME_ELAPSED
als Metrik verwende. Dieses Setup berücksichtigt die Art und Weise, wie OpenGL-Befehle asynchron mit der CPU ausgeführt werden. Siehe opengl.org/registry/specs/ARB/timer_query.txtAntworten:
Verwenden Sie
glGetUniformLocation
, um den Standort der Uniform zu ermitteln? Wenn die Uniform optimiert wurde, gibt diese Funktion -1 zurück. Wenn Sie -1 als Standortargument angeben,glUniform1f
wird nichts an den Shader gesendet, was wahrscheinlich einige Zeit spart.quelle
Klingt nach einem Problem mit der Ausrichtung oder der Speichergröße. Vielleicht wird mit diesem einen erhöhten Float Ihr Speicherbedarf auf eine magische Zahl erhöht, die den MAC verlangsamt (ich verwende selbst keine MACs), aber höchstwahrscheinlich verursacht dies ein Ausrichtungsproblem.
Betrachten Sie eine C ++ - Typstruktur im Pseudocode:
Wenn diese Struktur normal mit einer int-Größe von 4 Bytes und einer Zeichengröße von 1 Byte erstellt werden darf, beträgt die Struktur 8 Bytes, nicht die erwarteten 5 Bytes. Dies liegt daran, dass, wenn ein Wort (4 Bytes in 32-Bit-Systemen) nicht an einer 4-Byte-Grenze ausgerichtet ist, die CPU mehr Arbeit leisten muss, um dieses Wort zu verschieben. Es ist eine einzelne Assembly-Anweisung, ein Wort (in diesem Fall int) zu verschieben, wenn es richtig ausgerichtet ist. Wenn es nicht richtig ausgerichtet ist, wird die Hälfte des Wortes verschoben, ein Zeiger wird geändert und dann die andere Hälfte, was die Dinge verlangsamt. Daher versucht eine Struktur normalerweise, sich beim Kompilieren richtig auszurichten.
Wenn Sie so etwas wie #pragma packen würden, das die nicht verwendeten Füllbytes entfernen würde, wäre die Größe die erwarteten 5 Bytes und die Dinge wären langsamer.
Ich denke, Sie müssen sich ansehen, wo Sie diesen Float deklarieren und was unmittelbar davor und danach deklariert wird, um herauszufinden, woher Ihre möglichen Speicherausrichtungsprobleme stammen.
quelle