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.