ストリーミング(10ms未満)には非常に短い待ち時間のテクスチャを必要とするプログラムを作成しています。これはストリーミングにはうってつけのGL_ARB_buffer_storage
を使用して実装しました。OpenGLによるバッファリングの防止
しかし、ブロックする前にスワップバッファを呼び出すときにNVidiaパイプラインが2〜8フレームをバッファすることを発見しました。これを防ぐ必要があります。私がやっていること
は以下の通りです:
次に描画スレッドで私は次の操作を行いuint64_t detectPresentTime()
{
// warm up first as the GPU driver may have multiple buffers
for(int i = 0; i < 10; ++i)
glxSwapBuffers(state.renderer);
// time 10 iterations and compute the average
const uint64_t start = microtime();
for(int i = 0; i < 10; ++i)
glxSwapBuffers(state.renderer);
const uint64_t t = (microtime() - start)/10;
// ensure all buffers are flushed
glFinish();
DEBUG_INFO("detected: %lu (%f Hz)", t, 1000000.0f/t);
return t;
}
:
uint64_t presentTime = detectPresentTime();
if (presentTime > 1000)
presentTime -= 1000;
while(running)
{
const uint64_t start = microtime();
glClear();
// copy the texture to the screen
glxSwapBuffers();
const uint64_t delta = microtime() - start;
if (delta < presentTime)
{
glFlush();
usleep(delta);
glFinish();
}
}
このソリューションは、NVIDIAのハードウェア上で素晴らしい作品が、計算しないと報告されていますAMD GPUでの適切な現在の時間。
これを行うより良い方法はありますか?私はglFinish
が通常はプロファイリング以外のアプリケーションでは使用されるべきではないことを知っていますが、GPUパイプラインがフレームをバッファリングしないようにする別の方法はありません。
編集:興味のある人にとって、これはLinux上でFastSyncを効果的にエミュレートしますが、vsyncを無効にすることはありません。
EDIT2:おそらく現時点機能が少し異なる実装する必要があります。
uint64_t detectPresentTime()
{
glFinish();
// time 10 iterations and compute the average
const uint64_t start = microtime();
for(int i = 0; i < 10; ++i)
{
glxSwapBuffers(state.renderer);
glFinish();
}
const uint64_t t = (microtime() - start)/10;
DEBUG_INFO("detected: %lu (%f Hz)", t, 1000000.0f/t);
return t;
}
OpenGLのウィキがこのことについて興味深い記事があります。https://www.khronos.org/opengl/wiki/Swap_Interval – bernie