2012-10-17 12 views
6

Ich habe ein SDL/OpenGL-Spiel, ich arbeite zum Spaß. Ich bekomme durchschnittlich ordentliche FPS, aber die Bewegung ist ziemlich abgehackt, weil SDL_GL_SwapBuffers() nach dem Zufallsprinzip eine lange Zeit benötigt, um zu verarbeiten. Wenn Texturen geladen und in den Puffer geschrieben werden, dauert es manchmal 100ms! Ich habe viel von meinem Code abgeschnitten, um herauszufinden, ob ich etwas falsch gemacht habe, aber ich hatte nicht viel Glück. Wenn ich dieses Bare-Bones-Programm starte, blockiert es immer noch bis zu 70ms.SDL_GL_SwapBuffers() ist intermittierend langsam

Main:

// Don't forget to link to opengl32, glu32, SDL_image.lib 

// includes 
#include <stdio.h> 

// SDL 
#include <cstdlib> 
#include <SDL/SDL.h> 

// Video 
#include "videoengine.h" 

int main(int argc, char *argv[]) 
{ 
    // begin SDL 
    if (SDL_Init(SDL_INIT_VIDEO) != 0) 
    { 
     printf("Unable to initialize SDL: %s\n", SDL_GetError()); 
    } 

    // begin video class 
    VideoEngine videoEngine; 

    // BEGIN MAIN LOOP 
    bool done = false; 
    while (!done) 
    { 
     int loopStart = SDL_GetTicks(); 

     printf("STARTING SWAP BUFFER : %d\n", SDL_GetTicks() - loopStart); 
     SDL_GL_SwapBuffers(); 


     int total = SDL_GetTicks() - loopStart; 
     if (total > 6) 
      printf("END LOOP : %d ------------------------------------------------------------>\n", total); 
     else 
      printf("END LOOP : %d\n", total); 

    } 
    // END MAIN LOOP 

    return 0; 
} 

My "Videoengine" Konstruktor:

VideoEngine::VideoEngine() 
{ 
    UNIT = 16; 
    SCREEN_X = 320; 
    SCREEN_Y = 240; 
    SCALE = 1; 


    // Begin Initalization 

     SDL_Surface *screen; 

     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // [!] SDL_GL_SetAttributes must be done BEFORE SDL_SetVideoMode 

     screen = SDL_SetVideoMode(SCALE*SCREEN_X, SCALE*SCREEN_Y, 16, SDL_OPENGL); // Set screen to the window with opengl 
     if (!screen) // make sure the window was created 
     { 
      printf("Unable to set video mode: %s\n", SDL_GetError()); 
     } 

     // set opengl state 
     opengl_init(); 

    // End Initalization 

} 

void VideoEngine::opengl_init() 
{ 
    // Set the OpenGL state after creating the context with SDL_SetVideoMode 

     //glClearColor(0, 0, 0, 0);        // sets screen buffer to black 
     //glClearDepth(1.0f);          // Tells OpenGL what value to reset the depth buffer when it is cleared 
     glViewport(0, 0, SCALE*SCREEN_X, SCALE*SCREEN_Y);  // sets the viewport to the default resolution (SCREEN_X x SCREEN_Y) multiplied by SCALE. (x,y,w,h) 
     glMatrixMode(GL_PROJECTION);       // Applies subsequent matrix operations to the projection matrix stack. 
     glLoadIdentity();          // Replaces the current matrix with the identity matrix 
     glOrtho(0, SCALE*SCREEN_X, SCALE*SCREEN_Y, 0, -1, 1); //describes a transformation that produces a parallel projection 
     glMatrixMode(GL_MODELVIEW);       // Applies subsequent matrix operations to the projection matrix stack. 
     glEnable(GL_TEXTURE_2D);        // Need this to display a texture 
     glLoadIdentity();          // Replaces the current matrix with the identity matrix 
     glEnable(GL_BLEND);          // Enable blending for transparency 
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  // Specifies pixel arithmetic 
     //glDisable(GL_LIGHTING);        // Disable lighting 
     //glDisable(GL_DITHER);         // Disable dithering 
     //glDisable(GL_DEPTH_TEST);        // Disable depth testing 

     //Check for error 
     GLenum error = glGetError(); 
     if(error != GL_NO_ERROR) 
     { 
     printf("Error initializing OpenGL! %s\n", gluErrorString(error)); 
     } 

    return; 
} 

Ich fange vielleicht zu denken, ich habe ein Hardware-Problem? Ich hatte dieses Problem nie mit einem Spiel.

+0

Haben Sie Vsync aktiviert? – Tim

+0

Nein, ich glaube nicht, nachdem ich das gelesen habe -http: //stackoverflow.com/questions/589064/how-to-enable-vertical-sync-in-opengl Ich denke, was passieren kann, ist Aufruf SwapBuffers () ohne Zeit für die Verarbeitung zu geben, kann es dazu führen, dass es sich aufhängt oder eine Schleife bildet. Ich werde noch mehr lesen und schauen, ob ich etwas finden kann, das das unterstützt. – Alden

+2

[Toss] (http://www.msarnoff.org/sdb/) ein 'SDL_Delay (1)' nach dem Pufferwechsel, sehen Sie, was es zu Ihrem Frame mal macht. – genpfault

Antwort

2

SDL verwendet die Erweiterung SwapIntervalEXT, so dass Sie sicherstellen können, dass die Puffer-Swaps so schnell wie möglich sind (VSYNC deaktiviert). Auch Puffer-Swap ist keine einfache Operation, OpenGL muss den Inhalt von Back-Puffern in Front-Puffer für den Fall kopieren, den Sie glReadPixels() möchten. Dieses Verhalten kann mit WGL_ARB_pixel_format unter Verwendung WGL_SWAP_EXCHANGE_ARB gesteuert werden (Sie können über all diese Sachen in den Spezifikationen lesen; jetzt bin ich nicht sicher, ob es eine Alternative zu dem für Linux gibt).

Und dann noch das Windowing-System. Das kann tatsächlich viel Ärger verursachen. Außerdem, wenn einige Fehler generiert werden ...

Dieses Verhalten ist wahrscheinlich in Ordnung, wenn Sie auf einer kleinen mobilen GPU laufen.

SDL_GL_SwapBuffers() enthält nur einen Anruf an glxSwapBuffers()/wglSwapBuffers() so gibt es keine Zeit dort verbracht.

+3

Es heißt "swap" Puffer genau, weil keine vernünftige Implementierung tatsächlich eine Kopie durchführt. –

+0

@BenVoigt Nun, anscheinend tut WGL - lesen ['WGL_SWAP_EXCHANGE_ARB' Verwandte Dokumente] (http://oss.sgi.com/projects/ogl-sample/registry/ARB/wgl_pixel_format.txt) (Ich bestreite nicht Ihren Kommentar über geistige Gesundheit, obwohl). Der Grund dafür ist, den Inhalt des Puffers auch nach dem Austausch lesen zu können (nicht sicher, warum jemand das wollte), und das ist das Standardverhalten. Indem Sie 'WGL_SWAP_EXCHANGE_ARB' aktivieren, bestätigen Sie, dass Sie verstehen, dass nach dem Austausch die Puffer ausgetauscht werden und Sie nicht mehr zu Ihren Daten gelangen. –

+0

Sind Sie sicher, dass Sie nicht explizit nach gültigen Daten im Puffer fragen müssen? Dieser 'WGL_SWAP_METHOD_ARB' Parameter hat drei Optionen, und es macht nicht klar, was der Standard ist. –