OpenGL이 실제로 화면을 업데이트하는 데 시간이 얼마나 걸립니까?


9

키 입력에 대한 응답으로 다른 것을 그리는 C에 간단한 OpenGL 테스트 앱이 있습니다. (Mesa 8.0.4, NVIDIA GTX650이 설치된 PC에서 Mesa-EGL 및 GLFW, Ubuntu 12.04LTS로 시도) 추첨은 매우 간단하고 빠릅니다 (삼각형의 회 전형). 내 테스트 코드는 어떤 식 으로든 프레임 속도를 의도적으로 제한하지 않으며 다음과 같이 보입니다.

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

나는 이것을 매우 신중하게 시간을 정했고, 한 번 eglSwapBuffers()(또는 glfwSwapBuffers같은 것)에서 다음 번까지의 시간 은 ~ 16.6 밀리 초라는 것을 알았습니다 . 전화가 끝나고 eglSwapBuffers()다음 전화가되기 직전 까지 걸리는 시간은 그 내용이 매우 단순하지만 그보다 약간 적습니다. 스왑 버퍼 호출에 걸리는 시간은 1ms 미만입니다.

그러나 앱이 키를 누르면 화면에 실제로 나타나는 변경에 대한 응답으로 그림이 바뀌는 시간 은> 150ms (약 8-9 프레임 가치)입니다. 이것은 60fps에서 화면과 키보드의 카메라 녹화로 측정됩니다.

따라서 질문 :

  1. 스왑 버퍼 호출 사이에 드로우가 어디에 버퍼링되고 실제로 화면에 표시됩니까? 왜 지연? 앱이 항상 화면보다 많은 프레임을 그리는 것처럼 보입니다.

  2. OpenGL 응용 프로그램으로 화면을 즉시 그릴 수있는 방법은 무엇입니까? (즉 : 버퍼링 없음, 그리기가 완료 될 때까지 막기; 높은 처리량이 필요없고 낮은 대기 시간이 필요합니다)

  3. 위의 즉각적인 추첨을 가능한 빨리하기 위해 응용 프로그램은 무엇을 할 수 있습니까?

  4. 응용 프로그램은 현재 화면에 실제로 무엇이 있는지 어떻게 알 수 있습니까? (또는 현재 버퍼링 지연이 얼마나 오래 / 얼마나 많은 프레임입니까?)


키보드가 애플리케이션을 실제로 렌더링하는 데 걸리는 시간을 알리는 데 걸리는 시간을 분리 할 수 ​​있습니까?
ThorinII

@ 토린 II : 페어 포인트. 병렬 포트 등의 LED를 사용하여 해킹을 설정하여 앱이 실제로 키를 누를 때를 알 수 있습니다. 그래도 fgetc (stdin)입니다. 얼마나 느릴 수 있습니까? : /
Alex I

glFlush가 모든 명령을 즉시 플러시하는 데 사용되었다는 인상을 받았습니다.
Programmdude

1
@AlexI이 gamedev.stackexchange.com/questions/66543/… 확인하면 도움이 될 것입니다.
concept3d

1
@ concept3d : 예, 기본적으로 대답했습니다. 추가 담당자가 필요하다고 생각했습니다. :) 분명히 상을 받기 위해 하루를 기다려야합니다.
Alex I

답변:


6

CPU에서 호출 된 모든 드로잉 API 함수는 GPU에 의해 나중에 실행될 수 있도록 GPU 명령 링 버퍼 에 제출됩니다 . 이것은 OpenGL 함수가 대부분 비 차단 함수라는 것을 의미합니다. 따라서 CPU와 GPU가 동시에 작동합니다.

가장 중요한 점은 응용 프로그램이 CPU 또는 GPU 바인딩 일 수 있다는 것입니다. glFinish를 호출하면 CPU가 더 많은 시간이 걸리고 CPU가 정지 될 수있는 경우 응용 프로그램이 GPU에 바인딩 된 경우 CPU가 그리기 명령을 완료 할 때까지 기다려야합니다. GPU가 드로잉 명령을 마치고 CPU가 너무 오래 걸리면 응용 프로그램이 CPU에 바인딩됩니다.

그리고 사이에 차이가 있음을 유의 glFlush하고 glFinish.

glFlush: GL에 이전에 전송 된 모든 명령이 유한 시간 내에 완료되어야 함을 나타냅니다.

glFinish: 모든 이전 GL 명령을 강제로 완료합니다. GL 클라이언트와 서버 상태 및 프레임 버퍼에 대해 이전에 발행 된 명령의 모든 효과가 완전히 실현 될 때까지 완료가 리턴되지 않습니다. "

glXSwapBuffers 는 암시적인 glFlush를 수행하기 전에 수행합니다. 후속 OpenGL 명령은 glXSwapBuffers를 호출 한 직후에 발행 될 수 있지만 버퍼 교환이 완료 될 때까지 실행되지 않습니다.

실제 프레임 시간은 두 CPU / GPU 중 어느 것이 작업을 완료하는 데 더 많은 시간이 걸리는지에 따라 결정됩니다.


이것은 매우 도움이됩니다. 가능한 수정 사항 : opengl.org/sdk/docs/man2/xhtml/glXSwapBuffers.xml "glXSwapBuffers는 반환하기 전에 암시적인 glFlush를 수행합니다"이것은 실제로 glFinish를 수행하지 않으므로 명령 버퍼는 상당히 많은 스왑 버퍼가 반환되면 그 안에 넣습니다.
Alex I

... 또한 가장 흥미로운 점은 매우 간단한 테스트 응용 프로그램이 CPU 제한이 아니며 CPU에 제한이 없으며 여기에서해야 할 일이 많지 않다는 것입니다.하지만 다른 방법으로 프레임 속도가 낮습니다 (모니터와 정확히 동일 함) 새로 고침 빈도 ??) 및 높은 대기 시간 (명령 버퍼로 인해 실제로 해당 부분을 잘 설명했습니다).
Alex I

both low framerate (exactly same as monitor refresh rate??VSync를 명시 적으로 사용하지 않는 한 @AlexI 아니요.
concept3d

@AlexI 또한 프레임 시간이 FPS와 다르다는 것을 지적하고 프레임 시간을 사용하여 선형이기 때문에 응용 프로그램을 프로파일 링하십시오. 반면에 FPS는 선형이 아닌 측정이 좋지 않습니다.
concept3d

vsync를 명시 적으로 사용하고 있지 않습니다. defauls 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과 같은 것을 사용하여 애플리케이션 레벨에서이를 요청할 수 없습니다.


Andon : 좋은 정보입니다. 감사합니다. 내가보고있는 것은 부분적으로 이중 버퍼링이라고 생각하지만 "스왑이 발생하기 전에 백 버퍼를 수정하려고 시도해야합니다"-왜? 스왑을 포함하여 모든 것이 명령 버퍼로 전송 될 수있는 것처럼 들린다 :)
Alex I

"대부분의 GL 윈도우 시스템 API가 사용하는 백 버퍼 수를 명시 적으로 제어합니다 (0 개의 단일 버퍼 또는 1 개의 이중 버퍼 제외)-하나의 단일 / 더블 버퍼를 어떻게 제어합니까?
Alex I

@ AlexI : 명령이 차단으로 이어질 수있는 이유와 관련하여 언어를 명확히했습니다. 다른 API에는 render-ahead라는 개념이 있는데, 이는 사실상 명령 대기열의 깊이입니다. 단일 / 이중 버퍼링 제어에 대해서는 렌더링 컨텍스트를 만들 때 선택한 픽셀 형식으로 제어됩니다. WGL에서 단일 또는 이중 버퍼를 선택할 수 있지만 이중 버퍼를 선택하면 사용자가 드라이버를 설정 한 경우 드라이버가 실제로 2 개의 백 버퍼를 생성 할 수 있습니다 (따라서 이중 버퍼링이 3 중 버퍼링이 됨).
Andon M. Coleman

실제로 너무 많은 프레임을 렌더링하지 않으려면 블로킹이 줄어들지 만 대기 시간이 길어지기 때문입니다. 지연 시간을 최소화하는 가장 좋은 방법은 실제로 glFinish (...)버퍼 교체 후 즉시 호출하는 것 입니다. 명령 대기열이 지워지지 만 GPU와 CPU가 동기화됨을 의미합니다 (GPU를 항상 작동 상태로 유지하려는 경우에는 좋지 않습니다).
Andon M. Coleman

1

이 실험에 익숙하다고 생각 하십니까?

본질적으로 John Carmack은 비슷한 작업을 수행하여 화면을 기록하고 화면으로 전송되는 타이밍 픽셀을 기록했습니다. 그는 많은 대기 시간이 화면에서 나왔다는 것을 발견했습니다. 다른 요인은 키보드, 비디오 드라이버 및 프로그램 자체의 입력 지연으로 인한 입력 지연이었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.