2014-01-08 7 views
1

내 문제 :OpenGLES 2.0에서 출력 이미지 캐싱

화면에 opengles 2.0으로 렌더링해야하는 비디오가 있습니다 (말하면 25FPS). 비디오를 읽으려면 해당 비디오를 OpenGL es 텍스처로 디코딩하는 디코더를 사용합니다. 렌더 패스를 사용하여이 텍스처를 화면에 그립니다.

내가해야하는 것은 디코더에서 이미지를 가져 와서 GPP로 업로드하고, 쉐이더 프로그램을 호출하고 이미지를 화면에 렌더링하는 것입니다. 비디오에 25FPS가 있다면 40ms 단위로 화면을 업데이트해야합니다 (1000ms/25FPS). 각 단계에서

I는 도도가 다음

  • 는 GPU 메모리
  • 화면을
  • 스왑 버퍼
를 렌더링하는 디코더
  • 푸시로 화상을 얻을

    지금까지 작동 중입니다. 이제 프레임을 디코딩 할 때 디코더가 40ms보다 오래 걸립니다. 그것은 항상 일어나는 것이 아니라 때때로 발생합니다.

    해결책은 캐시를 만드는 것입니다. 즉, 첫 번째 이미지를 표시하기 전에 즉 5 개의 이미지를 렌더링합니다. 이 문제는 비동기식으로 발생하므로 캐시를 빌드하고 화면을 동시에 렌더링 할 수 있어야합니다. 그렇게되면 더 이상 "유동적"이 아니기 때문에 비디오에서 볼 수 있습니다.

    내 질문 :

    • 는 대한 해결책이 있습니까?
    • 렌더링 버퍼의 배경 버퍼에 복사 할 수있는 버퍼 (?!)를 만들 수 있습니다. 그러면 버퍼의 종류와 함께 캐시를 만들고 그 버퍼를 블로킹하지 않고 백 버퍼에 복사 할 수 있습니다. 이 버퍼를 만드는 다른 스레드?

    또는

    • 어떻게 다른 버퍼와 백 버퍼를 채우기 위해?

  • 은 이미 시도 :

    • 렌더링 프레임 버퍼 (텍스처) 캐시로. 텍스처가 렌더링되어야한다는 점을 제외하고는 거의 완벽하게 작동합니다. 이것은 캐시 프레임이 빌드되고 화면 이미지가 빌드 된 경우 렌더 메쏘드를 뮤텍스 (/ 동기화)시켜야한다는 것을 의미합니다 (비동기식이기 때문에). 그렇지 않으면 프로그램이 충돌합니다. 그러나 동기 화는 비동기 적으로 수행하는 것이 중요합니다. 그래서 이것은 좋은 해결책이 아닙니다.

    답변

    1

    OpenGL에서 화면을 지우고 다시 그리지 않으면 이전 이미지가 유지됩니다. 새로운 프레임이 제 시간에 준비가되지 않았다면 아무것도하지 마십시오.

    두 개의 스레드가있는 것처럼 들리 겠지만 하나는 프레임을 디코딩하고 하나는 렌더링하는 것입니다. 이건 괜찮아.

    render()가 호출되고 새 프레임이 준비되지 않은 경우 렌더링 메서드가 즉시 반환되어야합니다.버퍼를 지우거나 스왑하지 마십시오. 화면이 보존됩니다.

    이제 사용자가/프레임을 두 번 반복 할 때 가끔 딸꾹질하는 경우가 있습니다. 25fps는 자연스럽지 않은 프레임 속도입니다 (OpenGL은 60/30/15/등 만 지원합니다). 따라서 화면 새로 고침 빈도와 완벽하게 일치하지 않습니다.

    당신은 이걸로 살 수 있습니다 (사용자는 눈치 채지 못할 것입니다). 또는 프레임을 버퍼링하여 30fps로 강제 재생할 수 있습니다.

    디코더와 렌더러 사이에 메시지 대기열을 배치하는 것이 좋습니다. 하나 또는 여러 개의 프레임이 될 수 있습니다. 배열, 링크 된 목록 또는 링 버퍼 일 수 있습니다. 이렇게하면 렌더링이 다른 텍스처를 그리는 동안 많은 캐시 된 텍스처로 디코더를 업로드 할 수 있습니다.

    디코더는 들어오는 프레임을 큐에 추가합니다. 렌더러는 고정 속도 (30fps)로 실행됩니다. N 개의 프레임이 버퍼링 될 때까지 렌더링을 일시 중지 할 수 있습니다.

    +0

    설명 : 두 스레드에서 OpenGL ES를 사용하는 것은 까다로울 수 있습니다. 업로드/그리기 (적어도 iOS 및 Nvidia Tegra에서)는 "그냥 작동합니다". 장치가 이것을 허용하지 않으면 뮤텍스에 OGL 컨텍스트를 래핑해야합니다. 각 스레드는 OGL을 호출하기 전에 컨텍스트를 다시 바인드합니다. 빠른 것을 유지하는 비법 : . 문맥이 thread에 바인드되고 있는지 어떤지를 테스트합니다. 필요한 경우에만 다시 바인딩하십시오. . 텍스처를 미리 할당하십시오. . 텍스처를 삭제하지 마십시오. 다시 사용하십시오. . 장치가 허용하는 경우 직접 텍스처 메모리로 디코딩하십시오 (건너 뛰기 glTexSubImage2D). 그런 다음 스레드 호출을 최대 하나의 OGL 메서드 (텍스처 업로드)로 디코딩합니다. 경합이 낮을 것입니다. –