2012-10-17 33 views
6

私は楽しみのために取り組んでいるsdl/openglゲームを持っています。 SDL_GL_SwapBuffers()がランダムに処理するのに時間がかかりすぎるため、平均的にはかなりのフレームレートが得られますが、動きは本当に不安定です。テクスチャをロードしてバッファに書き込むと、時には100ms以上かかることがあります。私は、私が間違っていたものかどうかを調べるために、たくさんのコードを削除しましたが、私は多くの運がなかったのです。私がこの裸の骨プログラムを実行すると、時には最大70msまでブロックされます。SDL_GL_SwapBuffers()が断続的に遅いです

メイン:

// 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; 
} 

マイ "VideoEngine" コンストラクタ:

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; 
} 

私はおそらく、私は、ハードウェアの問題を持っていると思うし始めていますか?私はゲームでこの問題を経験したことはありません。

+0

vsyncを有効にしていますか? – Tim

+0

いいえ私はそれを読んだ後ではないと思います-http://stackoverflow.com/questions/589064/how-to-enable-vertical-sync-in-opengl 私はSwapBuffers )処理する時間を与えずに、ハングアップまたはループする可能性があります。私はもう少し読書をして、それをサポートするものが見つからないかどうかを見ます。 – Alden

+2

[Toss](http://www.msarnoff.org/sdb/)バッファスワップの後に 'SDL_Delay(1)'を実行すると、フレームタイムにどのような影響があるかを確認してください。 – genpfault

答えて

2

SDLではSwapIntervalEXTという拡張子を使用しているため、バッファスワップができるだけ高速になるようにすることができます(VSYNCは無効)。また、バッファスワップは単純な操作ではないので、OpenGLは、glReadPixels()にしたい場合にバックバッファの内容をフロントバッファにコピーする必要があります。この動作は、を使用してWGL_ARB_pixel_formatを使用して制御することができます(この仕様に関するすべてのことを読むことができますが、Linux用の代替手段があるかどうかはわかりません)。

さらに、ウィンドウシステムがあります。それは実際に多くの問題を引き起こす可能性があります。また、いくつかのエラーが発生した場合...

小さなモバイルGPUで動作している場合、この動作はおそらくOKです。

SDL_GL_SwapBuffers()にはglxSwapBuffers()/wglSwapBuffers()という呼び出しが含まれているため、そこには時間がありません。

+3

これは、実際に実装がコピーを実際に実行しないため、「スワップ」バッファーと呼ばれます。 –

+0

@BenVoigtまあ、明らかにWGLは - ['WGL_SWAP_EXCHANGE_ARB'関連のドキュメント](http://oss.sgi.com/projects/ogl-sample/registry/ARB/wgl_pixel_format.txt)を読んでいます(私はあなたのコメントに異議を唱えていませんしかし、正気については、)。この背後にある理由は、スワップ後でもバッファの内容を読み取ることができるようにすることです(誰かがそれをしたい理由がわからない)。これがデフォルトの動作です。 'WGL_SWAP_EXCHANGE_ARB'を有効にすることによって、スワップ後にバッファがスワップし、もはやデータにアクセスできなくなることを理解しています。 –

+0

バッファ内に有効なデータがあることを明示的に要求する必要はありませんか?その 'WGL_SWAP_METHOD_ARB'パラメータには3つのオプションがあり、どちらがデフォルトであるかはわかりません。 –

関連する問題