2016-07-08 2 views
2

사용자 정의보기 캔버스 드로잉 (postInvalidate()) 및 HardwareAcceleration이있는 간단한 2D 게임에서 작업중인 임. 몇 주 동안의 성능 분석을 통해 업데이트 및 드로잉 작업을 인터페이스 Choreographer.FrameCallback을 통해 VSYNC 펄스와 동기화하기로 결정했습니다. 생각하는 Im는 매끄러운 운동을 얻는 적당한 방법 thats이다.더블 버퍼링은 프레임 렌더링 속도를 늦춘다. systrace 분석

그러나 여전히 고르지 못한 움직임을 겪고 있습니다. 나는 systrace으로 분석했으며, 이는 BufferQueue와 관련이 있다는 것을 알게되었습니다. 이중 버퍼링이 설정되면 프레임 시간이 16ms를 초과합니다. 좀 설명 내 추적의 스크린 샷을했다 :

전체 그리기 작업은 자신의 새로운 빈 버퍼를 큐에서 제거 할 수있는 SurfaceFlinger의 (소비자)의 버퍼 출시를 기다립니다.

정상적인 행동인지 또는 그 원인이 될 수 있는지 알려주실 수 있습니까?

답변

1

그래프에 "SurfaceFlinger miss VSYNC"라는 메모가 있습니다.

그러나 BufferQueue 행을 보면 버퍼가 VSYNC 최종 기한 이후에 도착했음을 알 수 있습니다. SurfaceFlinger가 깨어 났지만 할 일이 없었습니다.

그런 다음 앱에 추가 버퍼가 제공되었으므로 두 개의 버퍼가 보류 중입니다. 모든 VSYNC에 버퍼를 계속 제공했기 때문에 대기열이 0 버퍼로 되돌아 가지 않았습니다. 대기열이 가득차면 추가 버퍼를 추가하려고하면 차단이 발생합니다.

FWIW, BufferQueue는 트리플 버퍼링입니다. 두 개는 대기열에 있고 하나는 디스플레이에 있습니다.

당신이 할 수있는 몇 가지가있다 : 마감일을 놓친 경우

  1. 이 응용 프로그램 드롭 프레임 되세요.
  2. 시간이 지났을 때 SurfaceFlinger가 프레임을 삭제할 프레임의 표시 시간을 지정하십시오.
  3. 의도적으로 한 번씩 프레임을 버려서 큐를 비워 둡니다. 선호하는 방법이 아닙니다.

# 2는 SurfaceView의 GLES에서만 작동하므로 무시할 수 있습니다.

# 1이 도움이 될 수 있습니다. example in Grafika을 볼 수 있습니다. "다음 VSYNC가 2ms 이내에 발사되거나 이미 발사 된 경우 현재 프레임 렌더링에 신경을 쓰지 마십시오." 보기/무효화 접근 방식은 GLES가하는 것과 동일한 세분화 된 제어 기능을 제공하지 않으므로 어떻게 작동하는지 잘 모르겠습니다.

바쁜 장치에서 애니메이션을 부드럽게하는 열쇠는 60fps에서 모든 프레임을 치지 않습니다. 열쇠는 델타 시간을 기반으로 업데이트를하는 것이므로 프레임을 두 개 드롭해도 상황이 원활하게 나타납니다.

그래픽 아키텍처에 대한 자세한 내용은 this doc을 참조하십시오.

+0

자세한 답변을 보내 주셔서 감사합니다. 나는 GLSurfaceView로 OpenGL ES 1 구현을하기로 결정했다. 이제 각 프레임에서 onDrawFrame() 메서드의 델타 시간을 측정합니다. 마지막 과거의 프레임 시간에 대한 보간법 (커다란 "stutter-jumps"제거)은 큰 발전이었습니다. 이제 내 게임은 매우 부드럽습니다! – methusa

관련 문제