Ich arbeite an einem Spiel, das CEGUI und Ogre verwendet. Kürzlich haben wir festgestellt, dass einige unserer Kunden mit GeForce4 MX 4000 eine schreckliche Leistung erzielen.
Nach einer Nacht mit dem Debuggen habe ich das Problem auf einen glDrawArrays-Aufruf im Ogre GL Renderer zurückgeführt. Die meisten Ausführungen dieses Aufrufs sind ziemlich schnell (<10 ms, was immer noch scheiße ist, aber für diese schreckliche Karte in Ordnung ist). Eine Ausführung der Renderfunktion GLRenderSystem :: _ dauert jedoch 3500 ms pro Frame.
Es wird nur eine TRIANGLE_LIST mit 54 Elementen gezeichnet. Bei allen anderen Aufrufen werden TRIANGLE_LISTs ähnlicher Größe gezeichnet, sodass nicht die Größe des Arrays oder sein Typ das Problem darstellt.
Ich habe:
- deaktivierte Fragment-Shader (der GF4 MX unterstützt sie nicht)
- deaktivierte Vertex-Shader (es unterstützt sie, aber CEGUI kann nur alle Arten von Shadern oder keinen von ihnen ausführen)
- Es wurde versucht, einen Anruf in der Nähe für Multitexturing zu deaktivieren
- Die Benutzeroberfläche, die ich zeichne, wurde massiv vereinfacht, sodass es sich nur um ein einziges CEGUI :: Window handelt
Aber ich schieße wirklich nur im Dunkeln. Ich bin in einer Windows-Umgebung. Was ist ein gutes Werkzeug, um den OpenGL-Status zum Zeitpunkt eines Funktionsaufrufs herauszufinden? Ich vermute, dass es eine besonders schweinische Textur oder einen Fragment-Shader gibt, der irgendwie durchrutscht und gerendert wird.
Wenn es keine Tools gibt, die das tun, was ich brauche, kann jemand Vorschläge machen, wie glDrawArrays auf einer alten Karte wirklich langsam gemacht werden können?
Aktualisieren:
- Ich griff nach GLTrace und verglich die Aufrufe, die sowohl einem schnellen als auch einem langsamen glDrawArrays vorausgingen. Sie sind absolut identisch, sie binden sogar die gleichen Textur-IDs.
- Ein konsistenter Unterschied besteht jedoch darin, dass der Aufruf, der langsam ausgeführt wird, der erste in jedem OGRE / Cegui-Rendering-Frame ist. Möglicherweise werden Texturdaten in jedem Frame auf die Grafikkarte kopiert (was lächerlich wäre und auf anderen Karten eindeutig nicht vorkommt ...). Update: Dies ist nicht der Fall - egal wo in der Warteschlange ich das fehlerhafte Objekt zeichne, es dauert immer noch ewig. Siehe unten.
- Es werden 3 Hauptobjekte gezeichnet: ein Hintergrund mit vollem Fenster (normales Weiß, wird mit einer 128x128-Textur strukturiert), eine kleinere rechteckige Beschriftung und Text in dieser Beschriftung. Die Verhältnisse zwischen ihren Ziehgeschwindigkeiten sind ungefähr gleich den Verhältnissen zwischen ihren Flächen
- Wenn ich erzwinge, dass das langsame Objekt mehrmals gezeichnet wird, anstatt die gesamte Renderwarteschlange zu zeichnen, ist es jedes Mal langsam, was bedeutet, dass es sich nicht um ein einmaliges Ladeproblem handelt.
Update für die aktuelle Theorie: Dies ist irgendwie ein Problem mit der Füllrate. Gibt es eine Möglichkeit, ein Fenster so zu konfigurieren, dass die Karte Probleme beim Ausfüllen hat? Wenn ich im Fenstermodus zeichne, wird das manchmal eine Karte durcheinander bringen? Mein Fenster hat keine Zweierpotenz-Dimensionen (oder Dimensionen, die einer Standardauflösung ähneln). Könnte das ein Chokepoint sein?
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW)
(GL_ARRAY_BUFFER
gegebenenfalls ersetzen ) verwenden.Antworten:
Ich habs:
Lösung: Anstelle des komplizierten Cegui-Setups siehe unten:
Ich werde das tun:
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)
Wenn Sie als zukünftiger Leser auch Ihr OgreGLRenderSystem ändern, werde ich diese Änderung in GLRenderSystem :: _ setTextureBlendMode in OgreGLRenderSystem.cpp vornehmen.
quelle
Ich habe es auch verstanden. Für mich war es ein Problem mit der Textur. Auf NVIDA lief es schnell. Aber meine optische Optimierung führte dazu, dass eine ATI-Karte schnell zurücktrat.
Ich arbeite mit einer Textur der Größe 4720 x 5600 (ungefähr) und moderne Karten funktionieren gut damit.
Ich habe versucht, Ränder mit Wrapmode = GL_CLAMP_TO_BORDER_ARB zu optimieren. Daher muss ich glTeximage2D das Randargument als mindestens == 1 liefern. Da die fragliche Karte in HW keine Grenze unterstützte, stellte sich heraus, dass es für einen Frame 20 Sekunden dauerte. Wenn Sie zu GL_CLAMP_TO_BORDER + border param == 0 zurückkehren, wird die Geschwindigkeit wieder erhöht.
quelle