2009-03-24 4 views
4

Dies ist, was passiert:Was verursacht bei der Präsentation des Renderbuffers schwankende Ausführungszeiten? (OpenGL)

  • Die drawGL Funktion am genauen Ende des Rahmens genannt wird dank einer usleep, wie vorgeschlagen. Dies hält bereits eine konstante Framerate aufrecht. Die tatsächliche Darstellung des Renderpuffers erfolgt mit drawGL(). Das Messen der dafür notwendigen Zeit gibt mir schwankende Ausführungszeiten, was zu einem Stottern in meiner Animation führt. Dieser Timer verwendet mach_absolute_time also es ist extrem genau.

  • Am Ende meines Rahmens, messen ich timeDifference. Ja, es ist im Durchschnitt 1 Millisekunde, aber es weicht sehr viel, von 0,8 Millisekunden bis 1,2 mit Spitzen von bis zu mehr als 2 Millisekunden.

Beispiel:

// Every something of a second I call tick 
-(void)tick 
{ 
    drawGL(); 
} 

- (void)drawGL 
{ 
    // startTime using mach_absolute_time; 

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

// endTime using mach_absolute_time; 
// timeDifference = endTime - startTime; 
} 

Mein Verständnis ist, dass, sobald der Framebuffer erstellt wurde, sollte die renderbuffer präsentiert immer den gleichen Aufwand, unabhängig von der Komplexität des Rahmens? Ist das wahr? Und wenn nicht, wie kann ich das verhindern?

Übrigens ist dies ein Beispiel für eine iPhone App. Wir sprechen hier von OpenGL ES, obwohl ich nicht glaube, dass es ein plattformspezifisches Problem ist. Wenn es ist, als was ist los? Und sollte das nicht nicht passiert sein? Und wenn ja, wie kann ich das verhindern?

Antwort

1

Die Abweichungen, auf die Sie stoßen, werden möglicherweise durch eine Vielzahl von Faktoren verursacht, einschließlich des OS-Schedulers, der einen anderen Prozess oder ähnliche Probleme hervorruft und CPU-Leistung liefert. Tatsächlich wird ein normaler Mensch keinen Unterschied zwischen 1 und 2 ms Renderzeiten feststellen. Filme laufen mit 25 fps, was bedeutet, dass jedes Bild für ungefähr 40ms gezeigt wird und für das menschliche Auge flüssig aussieht.

Wie für Animation Stottern sollten Sie untersuchen, wie Sie konstante Animationsgeschwindigkeit beibehalten. Die häufigsten Ansatz, den ich gesehen habe, sieht in etwa wie folgt aus:

while(loop) 
{ 
    lastFrameTime; // time it took for last frame to render 
    timeSinceLastUpdate+= lastFrameTime; 

    if(timeSinceLastUpdate > (1 second/DESIRED_UPDATES_PER_SECOND)) 
    { 
    updateAnimation(timeSinceLastUpdate); 
    timeSinceLastUpdate = 0; 
    } 

    // do the drawing 

    presentScene(); 
} 

Oder Sie könnten nur lastFrameTime passieren jeden Rahmen updateAnimation und zwischen Animation Zuständen interpolieren. Das Ergebnis wird noch flüssiger.

Wenn Sie bereits etwas wie oben beschrieben verwenden, sollten Sie vielleicht in anderen Teilen Ihrer Render-Schleife nach Schuldigen suchen. In Direct3D waren die kostspieligen Dinge, Primitive zu zeichnen und Render-Zustände zu ändern, also sollten Sie vielleicht nach OpenGL-Analoga suchen.

+0

Ich habe ja schon mal meine Berechnungen, um eine stabile Framerate zu erhalten. Die eigentliche Zeichnung findet immer am exakten Ende des Rahmens statt. (Ich verwende einen Schlaf-Timer dafür) Ich werde die Frage dafür klären. – Kriem

0

Es ist aus mehreren Gründen am besten, sich nicht auf eine hohe konstante Bildrate zu verlassen. Das wichtigste ist, dass das Betriebssystem etwas im Hintergrund ausführt, das die Vorgänge verlangsamt. Besser, einen Timer zu testen und herauszufinden, wie viel Zeit an jedem Frame vergangen ist, sollte dies eine reibungslose Animation gewährleisten.

0

Ist es möglich, dass der Timer nicht auf die Subms-Ebene genau ist, obwohl Dezimale 0,8 -> 2,0 zurückgegeben werden?

+0

Könnte sein. Es ist ein NSTimer. Trotzdem scheint die Framerate zu stottern. – Kriem

1

Mein Lieblings OpenGL Ausdruck aller Zeiten: "Implementierung spezifisch". Ich denke, es gilt hier sehr gut.

+0

Könnten Sie das näher erläutern? – Kriem

+0

Ich glaube nicht, dass die Spezifikation absolut verlangt, dass die Renderzeit für nachfolgende Frames mit gleichem Inhalt absolut gleich sein muss. Das heißt, der GPU-Hersteller darf wahrscheinlich die Zeit schwanken lassen. –

1

Eine schnelle Suche nach mach_absolute_time Ergebnissen in diesem Artikel: Link

Sieht aus wie Präzision dieser Timer auf einem iPhone ist nur 166,67 ns (und vielleicht noch schlimmer). Das erklärt zwar den großen Unterschied, erklärt aber nicht, dass überhaupt ein Unterschied besteht.

Die drei wichtigsten Gründe dafür sind wahrscheinlich:

  • Unterschiedliche Ausführungspfade während renderbuffer Präsentation. Es kann viel passieren in 1ms und nur weil Sie die gleichen Funktionen mit den gleichen Parametern aufrufen, heißt das nicht, dass die exakt gleichen Anweisungen ausgeführt werden. Dies gilt insbesondere, wenn andere Hardware beteiligt ist.
  • Interrupts/andere Prozesse, es gibt immer etwas anderes, das die CPU ablenkt. Soweit ich weiß, ist das iPhone OS kein Echtzeit-Betriebssystem und daher gibt es keine Garantie dafür, dass ein Vorgang innerhalb eines bestimmten Zeitlimits abgeschlossen wird (und sogar ein Echtzeit-OS wird Zeitvariationen haben).
  • Wenn noch andere OpenGL-Aufrufe von der GPU verarbeitet werden, die presentRenderbuffer möglicherweise verzögern. Das ist am einfachsten zu testen, rufen Sie einfach glFinish() auf, bevor Sie die Startzeit erhalten.
Verwandte Themen