2017-12-07 17 views
6

나는 스트리밍을 위해 매우 효과적 인 GL_ARB_buffer_storage과 찢어지지 않도록하는 vsync를 사용하여 스크린 스트리밍 (10ms 미만)에 매우 낮은 대기 시간 텍스처가 필요한 프로그램을 작성하고 있습니다.버퍼링 프레임에서 OpenGL 방지

그러나 NVIDIA 파이프 라인이 차단되기 전에 스왑 버퍼를 호출 할 때 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(); 
    } 
} 

이 솔루션은 엔비디아 하드웨어에서 잘 작동하지만를 계산하지보고되고있다 AMD GPU에서 적절한 현재 시간.

더 좋은 방법이 있나요? 프로파일을 제외하고는 보통 glFinish을 응용 프로그램에서 사용하면 안되지만 GPU 파이프 라인이 프레임을 버퍼링하지 않도록하는 다른 방법을 찾을 수 없습니다.

편집 : 관심있는 사람들을 위해 이것은 Linux에서 FastSync를 효과적으로 에뮬레이션하지만 vsync를 비활성화하지 않습니다.

Edit2가 : 다음을 기다릴 것이 가능이를 사용하여, SGI_video_sync라는 작은 알려진 OpenGL을 확장가,

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

는 OpenGL 위키는 이에 대한 흥미로운 기사가 ​​있습니다 https://www.khronos.org/opengl/wiki/Swap_Interval – bernie

답변

2

내가 대답을 발견 : 아마도 현재의 기능은 서로 다른 비트를 구현해야합니다 틀.

예 :

glFlush(); 
uint remainder; 
glXWaitVideoSyncSGI(1, 0, &remainder);