OpenGLが実際に画面を更新するのにどのくらい時間がかかりますか?


9

キー入力に応じてさまざまなものを描画する単純なOpenGLテストアプリをCで作成しています。(Mesa 8.0.4、Mesa-EGLおよびGLFW、NVIDIA GTX650を搭載したPC上のUbuntu 12.04LTSで試した)。ドローは非常にシンプル/高速です(回転三角形タイプのもの)。私のテストコードは、フレームレートを意図的に制限するものではなく、次のようになっています。

while (true)
{
    draw();
    swap_buffers();
}

私はこれを非常に注意深く計時しており、1つのeglSwapBuffers()(またはglfwSwapBuffers、同じもの)呼び出しから次の呼び出しまでの時間は〜16.6ミリ秒であることがわかりました。eglSwapBuffers()描画されたものは非常に単純ですが、呼び出し後から次の呼び出しの直前までの時間は、それより少しだけ短くなります。スワップバッファの呼び出しにかかる時間は1ミリ秒未満です。

ただし、アプリがキーの押下に応じて描画内容を変更してから実際に画面に表示されるまでの時間は、> 150ms(約8〜9フレーム)です。これは、画面とキーボードを60 fpsでカメラで記録して測定されます。

したがって、質問:

  1. スワップバッファーの呼び出しと実際に画面に表示される呼び出しの間の描画はどこにバッファーされますか?なぜ遅れるの?アプリが常に画面の前に多くのフレームを描画しているようです。

  2. OpenGLアプリケーションは、画面にすぐに描画するために何ができますか?(つまり、バッファリングなし、描画が完了するまでブロックするだけです。高スループットは必要ありません。低遅延が必要です)

  3. 上記の即時抽選をできるだけ早く行うためにアプリケーションは何ができますか?

  4. アプリケーションは現在、実際に画面上にあるものをどのようにして知ることができますか?(または、現在のバッファリング遅延はどのくらいの長さ/何フレームですか?)


キーボードがアプリケーションに通知するのにかかる時間と、実際にそれをレンダリングするのにかかる時間を分けることができますか?
ThorinII 2014年

@ThorinII:フェアポイント。おそらく、パラレルポートのLEDなどを使用して、アプリが実際にキーを押すタイミングを知るために、何かハックを設定できます。それでも、それは単にfgetc(stdin)ですが、それはどれほど遅くなることができますか?:/
アレックスI

glFlushを使用してすべてのコマンドを即座にフラッシュするという印象を受けました。
Programmdude

1
@AlexIはこのゲームをチェックするdev.stackexchange.com/questions/66543/…役立つかもしれません
concept3d

1
@ concept3d:はい、基本的には回答されます。追加の担当者が必要だと思っただけです。
Alex I

回答:


6

CPUから呼び出された描画API関数はGPU コマンドリングバッファーに送信され、後でGPUによって実行されます。これは、OpenGL関数がほとんど非ブロッキング関数であることを意味します。したがって、CPUとGPUは並行して動作します。

注意すべき最も重要なことは、アプリケーションがCPUまたはGPUにバインドされている可能性があることです。glFinishを呼び出すと、CPUはGPUが描画コマンドを完了するのを待機します。GPUに時間がかかり、CPUがストールする可能性がある場合は、アプリケーションはGPUにバインドされています。GPUがコマンドの描画を完了し、CPUがglFinishに時間がかかりすぎる場合、アプリケーションはCPUにバインドされています。

そして、の間に差があることに注意してくださいglFlushとはglFinish

glFlush:GLに以前に送信されたすべてのコマンドが有限時間で完了する必要があることを示します。

glFinish:以前のすべてのGLコマンドを強制的に完了させます。GLクライアントとサーバーの状態で以前に発行されたコマンドからのすべての効果とフレームバッファーが完全に実現されるまで、完了は戻りません。」

glXSwapBuffersは、戻る前に暗黙的なglFlushを実行します。後続のOpenGLコマンドは、glXSwapBuffersを呼び出した直後に発行される可能性がありますが、バッファー交換が完了するまで実行されません。

実際のフレーム時間は、ほとんどの場合、2つのCPU / GPUのどちらが作業を完了するのにより多くの時間を費やしているかによって決まります。


これは非常に役立ちます。いくつかの可能な修正:opengl.org/sdk/docs/man2/xhtml/glXSwapBuffers.xml "glXSwapBuffersは、戻る前に暗黙的なglFlushを実行します"これは実際にはglFinishを実行していないようですので、コマンドバッファーにはかなりの量のスワップバッファが戻ったときの内容。
Alex I

...また、最も興味深い点は、私の非常に単純なテストアプリケーションはCPUもGPUも制限されておらず、ここで行う作業も多くないことです。リフレッシュレート??)と高レイテンシ(コマンドバッファのため、実際にはその部分を非常によく説明しています)。
Alex I 14

@AlexI both low framerate (exactly same as monitor refresh rate??いいえ、明示的にVSyncを使用している場合を除きます。
concept3d 2014年

@AlexIまた、フレームタイムはFPSとは異なることも指摘しておきます。線形であるため、フレームタイムを使用してアプリケーションのプロファイルを作成します。一方、FPSは線形ではない貧弱な測定です。
concept3d 2014年

私は明示的にvsyncを使用していません。デフォルトのvsync設定を変更するために何もしていません。OpenGLでどこを変更するかさえわかりません。ちょうど60fps(パーセント以内)になります。
Alex I

4

OpenGLが技術的に画面を更新することはありません。

これを行うGL(GLX、WGL、CGL、EGLなど)とは別のウィンドウシステムAPIがあります。これらのAPIを使用するバッファスワップは、通常、暗黙的に呼び出されますglFlush (...)が、一部の実装(WindowsのGDIラスタライザなど)では、完全に実行されますglFinish (...)

 

    *左側は、を通るICD(ハードウェア)パスSwapBuffers (...)です。右側には、GDI(ソフトウェア)パス。

VSYNCを有効にしてダブルバッファリングしている場合、保留中のスワップが発生する前にバックバッファーを変更するコマンドは、スワップまでストールする必要あります。コマンドキューの深さには制限があるため、この停止したコマンドは最終的にパイプラインで渋滞を引き起こします。これはSwapBuffers (...)、アプリケーションをブロックする代わりに、実際にはVBLANKが回転するまで、無関係なGLコマンドをブロックすることを意味します。結局のところ、スワップチェーンにあるバックバッファの数です。

すべてのバックバッファーが、まだフロントに移動されていない完成したフレームでいっぱいである限り、スワップバッファーは暗黙的にブロッキングを引き起こします。悲しいことに、ほとんどのGLウィンドウシステムAPIで使用されるバックバッファの数を明示的に制御する方法はありません(シングルバッファリング0またはダブルバッファリング1を除く)。ドライバーは、必要に応じて2つのバックバッファーを自由に使用できます(トリプルバッファリング)。ただし、GLXやWGLなどを使用してアプリケーションレベルでこれを要求することはできません。


アンドン:良い情報、ありがとうございます。私が見ているのは部分的にダブルバッファリングだと思いますが、「スワップが発生する前にバックバッファーを変更しようとするとブロックされる」-なぜですか?スワップを含め、すべてがコマンドバッファーに送信されるようです:)
Alex I

「ほとんどのGLウィンドウシステムAPIで使用されるバックバッファの数を明示的に制御する(シングルバッファリング0またはダブルバッファリング1を除く)」-シングル/ダブルバッファリングをどのように制御しますか?
Alex I

@AlexI:コマンドがブロッキングを引き起こす理由について、言語を明確にしました。他のAPIには、レンダーアヘッドと呼ばれる概念があります。これは、コマンドキューの深さです。シングル/ダブルバッファーの制御は、レンダリングコンテキストを作成するときに選択したピクセル形式によって制御されます。WGLでは、シングルバッファリングまたはダブルバッファリングを選択できますが、ダブルバッファリングを選択した場合、ユーザーがドライバを設定すると、ドライバは実際に2つのバックバッファを作成する可能性があります(したがって、ダブルバッファリングはトリプルバッファリングになります)。
Andon M. Coleman 2014

レンダリングをブロックしすぎないようにする一方で、レイテンシも増加するため、実際にはあまり多くのフレームを先にレンダリングしたくないでしょう。レイテンシを最小限に抑える最善の方法は、実際にはglFinish (...)バッファをスワップした直後に呼び出すことです。これにより、コマンドキューがクリアされますが、GPUとCPUが同期されることも意味します(GPUを常に動作させたい場合、これは適切ではありません)。
Andon M. Coleman

1

あなたはこの実験に精通していると思いますか?

基本的に、ジョンカーマックは同様のことを行って、画面に送信された画面とタイミングピクセルを記録しました。彼は待ち時間のかなりの部分が画面からのものであることを発見しました。他の要因は、キーボード、ビデオドライバーからの入力遅延、および/またはプログラム自体の実行です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.