OpenGL: Suche nach Performanceverschwendung



  • Ich bräuchte ein paar Anregungen, wie ich die Performance meiner 3D Engine ausbauen kann.

    http://vertex.art-fx.org/dreide222.zip das ist die neuste Version inklusive Quellcode.

    Hintergrund ist dieser, das ich immer mit einer fertigen 3D Engine vergleiche. Konkret: meine hatte 190 FPS die Vergleichsengine(Blitz3D) 320 FPS.

    Ich zeige euch einfach mal den Renderpass, der in diesem Beispiel konkret abläuft:

    Kamera:
     glDisable(GL_SCISSOR_TEST) // Da der Viewport den gesamten Bereich einnimmt.
    
     glMatrixMode(GL_PROJECTION)
     glLoadIdentity()
    
     glViewport(0, 0, 800, 600)
    
     gluPerspective(45.0/1.0, Float(800)/Float(600), 1.0, 1000.0)
    
     glScalef(1.0, 1.0, 1.0)
    
     glEnable(GL_DEPTH_TEST)
     glDepthFunc(GL_LEQUAL)
     glClear(GL_DEPTH_BUFFER_BIT)
    
     glClearColor(0.4, 0.6, 0.8, 1.0)
     glClear(GL_COLOR_BUFFER_BIT)
    
     glDisable(GL_FOG)
    
     glMatrixMode(GL_MODELVIEW)
     glLoadIdentity()
    
     glRotatef(-Self.Rotation[0], 1.0, 0.0, 0.0)
     glRotatef(-Self.Rotation[1], 0.0, 1.0, 0.0)
     glRotatef(-Self.Rotation[2], 0.0, 0.0, 1.0)
    
     glPushMatrix()
      Mesh-Rendern
     glPopMatrix()
    
    Mesh-Rendern:
     glTranslatef(Self.Position[0], Self.Position[1], Self.Position[2])
     glRotatef(Self.Rotation[0], 1.0, 0.0, 0.0)
     glRotatef(Self.Rotation[1], 0.0, 1.0, 0.0)
     glRotatef(Self.Rotation[2], 0.0, 0.0, 1.0)
     glScalef(Self.Scale[0], Self.Scale[1], Self.Scale[2])
    
     Alle Surfaces durchgehen
     {
      Surface-Rendern
     }
    
    Surface-Rendern:
     Materialeigenschaften-Setzen:
      glEnable(GL_CULL_FACE)
      glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 0.0)
    
      glShadeModel(GL_SMOOTH)
    
      glPolygonMode(Face, GL_FILL)
    
      glEnable(GL_BLEND)
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    
      glMaterialf(Face, GL_SHININESS, Self.Shininess)
      glMaterialfv(Face, GL_AMBIENT, Self.AmbientColor)
      glMaterialfv(Face, GL_DIFFUSE, Self.DiffuseColor)
      glMaterialfv(Face, GL_SPECULAR, Self.SpecularColor)
      glMaterialfv(Face, GL_EMISSION, Self.EmissiveColor)
    
      glEnableClientState(GL_TEXTURE_COORD_ARRAY)
    
     // Textur aktivieren
     glActiveTexture(GL_TEXTURE0)
    
     glBindBufferARB(GL_ARRAY_BUFFER, Self.VertexBuffer[2])
     glTexCoordPointer(2, GL_FLOAT, 0, Null)
    
     Textureeigenschaften-Setzen:
      glGetIntegerv(GL_MATRIX_MODE, Varptr(Matrix))
    
      glMatrixMode(GL_TEXTURE)
      glLoadIdentity()
    
      glTranslatef(Self.Position[0], Self.Position[1], 0.0)
      glRotatef(Self.Rotation, 0.0, 0.0, 1.0)
      glScalef(Self.Scale[0], Self.Scale[1], -1.0)
    
      glMatrixMode(Matrix)
    
      glDisable(GL_TEXTURE_CUBE_MAP)
      glDisable(GL_TEXTURE_GEN_S)
      glDisable(GL_TEXTURE_GEN_T)
      glDisable(GL_TEXTURE_GEN_R)
    
      glEnable(GL_TEXTURE_2D)
      glBindTexture(GL_TEXTURE_2D, Self.TextureID)
    
      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT)
      glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE)
    
     // Bind Vertex-Color
     glBindBufferARB(GL_ARRAY_BUFFER, Self.VertexBuffer[4])
     glColorPointer(4, GL_FLOAT, 0, Null)
    
     // Bind Normals
     glBindBufferARB(GL_ARRAY_BUFFER, Self.VertexBuffer[1])
     glNormalPointer(GL_FLOAT, 0, Null)
    
     // Bind Vertices
     glBindBufferARB(GL_ARRAY_BUFFER, Self.VertexBuffer[0])
     glVertexPointer(3, GL_FLOAT, 0, Null)
    
     // Bind TriangleBuffer
     glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, Self.TriangleBuffer)
    
     // Display Triangles
     glDrawElements(GL_TRIANGLES, Self.TriangleCount*3, GL_UNSIGNED_INT, Null)
    

    So sieht der Renderpass für ein Mesh mit 8000 Triangles, 16 Surfaces, 10 Materials und 3 Texturen aus.

    Wo hängt die größte Performance? Ist meinetwegen das ständige Deaktivieren des Scissor-Tests sehr verschwenderich? Also soetwas in der Richtung.

    Danke schonmal, wer sich die Mühe macht, mir fehlt es einfach noch an Erfahrung mit OpenGL.

    mfg olli



  • würd einfach mal um jede Operation nen Timer setzen und das Ergebnis in eine Datei schreiben, dann weißte, was am meisten Zeit beansprucht..



  • oder durch nen profiler jagen. mit mingw und gprof geht das sehr easy...



  • Ja, ich abreite hier mit BlitzMax und nicht mit MingW...

    Habe jetzt mal fast alle Befehle gemessen:

    glDisable(GL_SCISSOR_TEST) = 666 ms
    glMatrixMode(GL_PROJECTION) = 145 ms
    glLoadIdentity() = 607 ms
    glViewport(0, 0, 800, 600) = 820 ms
    gluPerspective(45.0/1.0, Float(800)/Float(600), 1.0, 1000.0) ~ 590100 ms
    
    glScalef(1.0, 1.0, 1.0) = 621 ms
    
    glEnable(GL_DEPTH_TEST) = 734 ms
    glDepthFunc(GL_LEQUAL) = 471 ms
    glClear(GL_DEPTH_BUFFER_BIT) ~ 1400 ms (nicht messbar)
    
    glClearColor(0.4, 0.6, 0.8, 1.0) = 1663 ms
    glClear(GL_COLOR_BUFFER_BIT) ~ 2000 ms (nicht messbar)
    
    glDisable(GL_FOG) = 851 ms
    
    glMatrixMode(GL_MODELVIEW) = 105 ms
    glRotatef(-127.5, 1.0, 0.0, 0.0) = 3634 ms
    
    glPushMatrix() + glPopMatrix() = 1451 ms
    
    glTranslatef(10.0, 20.0, 30.0) = 590
    glScalef(10.0, 20.0, 30.0) = 12863 ms
    
    --------------------------------------------------------------------------------
    
    glEnable(GL_CULL_FACE) = 482 ms
    glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, 0.0) = 632 ms
    
    glShadeModel(GL_SMOOTH) = 418 ms
    
    glPolygonMode(GL_FRONT, GL_FILL) = 505 ms
    
    glEnable(GL_BLEND) = 993 ms
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) = 393 ms
    
    glMaterialf(GL_FRONT, GL_SHININESS, 0.6) = 1106 ms
    glMaterialfv(GL_FRONT, GL_XXXXX, [0.2, 0.3, 0.4, 0.5]) ~ 391260 ms
    
    glEnableClientState(GL_TEXTURE_COORD_ARRAY) = 177 ms
    
    --------------------------------------------------------------------------------
    
    glActiveTexture(GL_TEXTURE0) = 123 ms
    glGetIntegerv(GL_MATRIX_MODE, Varptr(Matrix)) = 143 ms
    glMatrixMode(GL_TEXTURE) = 130 ms
    
    glDisable(GL_TEXTURE_CUBE_MAP) = 211 ms
    glDisable(GL_TEXTURE_GEN_S) = 171 ms
    glDisable(GL_TEXTURE_GEN_T) = 280 ms
    glDisable(GL_TEXTURE_GEN_R) = 189 ms
    
    glEnable(GL_TEXTURE_2D) = 370 ms
    
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT) = 598 ms
    glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE) = 385 ms
    

    Die Zeiten mit ~ musste ich aufrunden. glClear hat mein Rechner mehrmals abschmieren lassen.

    Das Meiste ist einfach nur Overhead, aber folgendes kann man Schlussfolgern:
    - glClear immer mit allen Buffern gemeinsam aufrufen
    - gluPerspective so wenig wie möglich aufrufen(event. eigene Rotine schreiben)
    - glMaterialfv so wenig wie möglich verwenden

    Was auch ganz interessant ist, dass glScale treiber- oder hardwarenäßig optimiert wurde. Wenn ein Parameter = 1.0 ist, so wird dieser anscheinend nicht beachtet.

    Die ganzen Tests liefen auf:

    Vendor:         Intel
    Renderer:       Intel 915G
    OpenGL-Version: 1.4.0 - Build 4.14.10.4020
    
    Prozessor: Intel pentium 4 CPU 2.80GHz (2 CPUs), ~2.8GHz
    
    Arbeitsspeicher: 1014MB RAM
    
    OS: Win2000 prof.
    

    mfg olli



  • Schau mal "Bottleneck Identification" auf diesen Folien an: http://www.ati.com/developer/gdc/PerformanceTuning.pdf



  • glScalef(10.0, 20.0, 30.0) = 12863 ms

    12 Sekunden für nen glScalef 😮

    Da ist aber etwas sehr übel! Oder steht ms nicht für Millisekunden (1 /1000)?



  • Andreas XXL schrieb:

    glScalef(10.0, 20.0, 30.0) = 12863 ms

    12 Sekunden für nen glScalef 😮

    Da ist aber etwas sehr übel! Oder steht ms nicht für Millisekunden (1 /1000)?

    Nicht für ein glScalef sondern für alle glScalef zusammen, die das Programm aufgerufen hat.


Anmelden zum Antworten