2

OSX でシンプルなグラフィカル アプリを作成しています。フレーム間のシステム時間の差をチェックすることで、フレームレートの監視を開始しました。数フレームごとに少しぶら下がっているようです。

アプリは、現在 200 fps (5 ミリ秒フレーム) に設定されている NSTimer オブジェクトで実行されます。メイン コードが遅いだけではないことを確認するために、[self.context flushBuffer]; を除くメイン ループ全体をコメント アウトしました。(もちろん、フレームレートのサンプリング コードも)。この単一の呼び出しを繰り返しても、一度に複数のフレームでハングします。コンソール出力の例を次に示します。

4
5
6
10
5
5
5
4
6
10
5
5
5
5
5
5
20
4
5
6
20
5
5
5

これは、各ループ反復間のミリ秒単位の時間です。200 fps では、フレームごとに約 5 ミリ秒になるはずですが、10、15、または 20 ミリ秒も繰り返しハングします。-initOpenGL 関数でわかるように、Vsyncing は無効になっています。

-(void)initOpenGL{
    NSOpenGLPixelFormatAttribute attributes[] = {NSOpenGLPFADoubleBuffer, 0};
    NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: attributes];
    self.context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
    [self.context setView:[self.window contentView]];
    [self.context makeCurrentContext];

    //Disable Vsync
    int temp = 0;
    [self.context setValues: &temp forParameter: NSOpenGLCPSwapInterval];

    glViewport(0, 0, windowWidth, windowHeight);
    glMatrixMode(GL_PROJECTION);
    glOrtho(0, windowWidth, 0, windowHeight, -1, 100);

    //Flip all textures right side up
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glScalef(1.0f, -1.0f, 1.0f);

    glMatrixMode(GL_MODELVIEW);

    glEnable(GL_SCISSOR_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

編集、新しい情報:これは、ダブルバッファリングとシングルバッファリングに関係があることを確認できます。DoubleBuffer 属性なしで NSOpenGLPixelFormat を初期化すると、200 fps で完全に実行されます。その属性では、私は吃音を続けています。

4

2 に答える 2

5

実際のレンダリング コード (投稿されていません) を知らなくても、考えられる原因の 1 つはNSTimer、そもそもフレーム レート コントロールに を使用することがそれほど優れたアイデアではないことです。ドキュメントを参照してください(強調を追加):

タイマーはリアルタイムのメカニズムではありません。タイマーが追加された実行ループ モードの 1 つが実行中で、タイマーの起動時間が経過したかどうかを確認できる場合にのみ起動します。典型的な実行ループが管理するさまざまな入力ソースのため、タイマーの時間間隔の有効な分解能は 50 ~ 100 ミリ秒程度に制限されます。

したがって、タイマーを 5 ミリ秒程度使用するという期待には、根本的な欠陥があります。

それに加えて、フレーム時間を 100% 一定にしない他の影響 (プロセスのスケジューリング、テクスチャのアップロード、OpenGL でのストールなど) が存在する場合があります。これらによって引き起こされるジッターは通常、はるかに小さいスケールになります。

于 2013-03-13T17:43:58.157 に答える
2

OSX で適切な同期が必要な場合は、CoreVideo DisplayLink を使用する必要があります。これは画面の垂直リフレッシュごとに呼び出されるコールバックであるため、画面が 60 FPS の場合、このコールバックは (別のスレッドで、OpenGL スレッドに注意してください) 毎秒 60 回呼び出され、それが OpenGL リフレッシュをトリガーする必要があります。 .

于 2015-07-24T09:15:40.833 に答える