태그 보관물: opengl

[WAYLAND] OPENGL 소프트웨어스택의 미래 (XDC 2014)

오늘은 얼마 전에 있었던 XDC 2014 에서 발표됐던 내용을 바탕으로 향후 OPENGL 소프트웨어스택이 어떤 방향으로 발전해나갈지를 간단히 정리해보려고 합니다. 그에 앞서 OPENGL 소프트웨어스택이 정확히 무엇을 의미하는지에 대해 간단히 살펴보도록 하겠습니다.

opengl-sw

위의 그림은 오픈소스 기반의 OPENGL 소프트웨어스택(MESA/DRM)의 구조를 간단히 표현한 것입니다. 계층적으로 보면 MESA/DRM 라이브러리와 드라이버가 있습니다. 우선 DRM 라이브러리는 미리 정의된 IOCTL 인터페이스를 이용해 DRM 드라이버를 단순 호출해주는 역할만을 하므로 길게 설명하지 않고, MESA 라이브러리와 DRM 드라이버에 대해 설명하도록 하겠습니다. (앞으로 DRM 이라고하면 커널 드라이버를 의미한다고 생각하시면 됩니다.)

OPENGL 소프트웨어스택이 하는 역할은 크게 보면 두 가지입니다. 첫 번째는 윈도우 시스템(X11, WAYLAND, …)을 지원하는 것이고, 두 번째는 하드웨어 가속을 지원하는 것입니다. 그렇다면 이를 위해 MESA 라이브러리와 DRM 드라이버는 각각 무슨 일을 할까요? 간단한 예를 들어 설명하면, 하드웨어 가속을 이용하여 OPENGL 렌더링을 하기 위해서는 GPU 에 렌더링을 위한 명령어 스트림을 전달해야 합니다. 그러기 위해서는 GPU 에서 접근할 수 있는 메모리를 할당받아서 필요한 명령어 스트림을 채워야겠죠. 이 때, 실제로 메모리를 할당해주는 역할을 DRM 드라이버가 하고, 명령어 스트림을 채워주는 역할은 MESA 가 하는 것입니다. 즉, 메모리 할당/해제와 같이 커널의 권한이 필요한 것은 DRM 드라이버가 하고, 나머지는 모두 MESA 가 한다고 보시면 됩니다. (사실 역할을 나누기 좀 애매한 부분도 있긴 하지만, 대략 이 정도로 이해하시면 무난할 것 같습니다.) 그래서 우리가 일반적으로 많이 듣는 윈도우 시스템을 지원하는 GLX, EGL 등과 OPENGL 버전 3 이나 4, ES 같은 것들은 실제로는 MESA 와 직접적으로 연관이 있습니다.

그럼 이제 윈도우 환경에서 OPENGL 을 어떻게 사용하는지 살펴보도록 하겠습니다. 우선, 클라이언트와 서버가 OPENGL 을 사용하는 방식에 대해 간단히 살펴보면, 클라이언트는 자기가 원하는 결과물을 렌더링해서 서버로 전달하는 일을 하고, 서버는 모든 클라이언트가 렌더링한 결과물을 받아서 실제 화면에 표시될 결과물을 렌더링한 후 디스플레이에 출력하는 일까지 합니다. 서버와 클라이언트는 렌더링하는 방식도 조금 다르고, 서버는 디스플레이 관리까지 해야하니 사용하는 인터페이스도 차이가 조금 있습니다. 다음은 클라이언트와 서버에서 사용하는 인터페이스들에 대한 설명입니다.

  • GL-API..클라이언트와 서버 모두가 사용하는, 렌더링을 하기 위해 사용하는 기본적인 드로잉 인터페이스입니다. (glVertex3f, …)
  • EGL-API(wl-client)..클라이언에서 사용하는 윈도우 시스템 관련 인터페이스로, 렌더링을 위한 버퍼를 생성하고, 렌더링 후에 서버에게 전달하는 일 등을 처리해줍니다.
  • EGL-API(wl-server)..서버에서 사용하는 윈도우 시스템 관련 인터페이스로, 클라이언트가 렌더링한 결과물을 받아서 사용할 수 있도록 준비하는 일 등을 처리해줍니다.
  • EGL-API(gbm)..서버에서 실제로 화면에 출력될 결과물을 렌더링하기 위해 사용하는 인터페이스입니다.
  • KMS-API..서버에서 렌더링한 최종 결과물을 실제 화면에 뿌리기 위해 사용하는 인터페이스입니다. (pageflip, …)

일단 클라이언트와 서버에서 사용되는 인터페이스들을 나누어보면 이 정도가 되겠습니다. 그럼 이제 본격적으로 XDC 2014 에서 발표된 OPENGL 소프트웨어스택과 관련된 발표들을 살펴보도록 하겠습니다. 이 발표들의 기본 목적은 딱 한 가지입니다. 현재 WAYLAND 를 기반으로 한 윈도우 매니저들이 MESA/DRM 에 기반한 EGL/KMS 인터페이스만을 지원하고 있기 때문에 상용 드라이버의 거취가 애매해지고 있습니다. 즉, 위에서 얘기했던 EGL-API 와 KMS-API 를 현재 상용 드라이버는 지원하지 않고 있기 때문에 앞으로 WAYLAND 기반 윈도우 매니저에서는 상용 드라이버를 사용할 수 없다는 것입니다. 그래서 이를 어떻게 해결해 나갈지에 대한 AMD 와 NVIDIA 측이 발표한 내용입니다.

http://www.x.org/wiki/Events/XDC2014/XDC2014DeucherAMD/amdgpu_xdc_2014_v3.pdf
첫 번째로 AMD 에서 발표한 내용을 살펴보도록 하겠습니다. AMD 는 상당히 적극적인 오픈소스 지원/통합 계획을 소개했습니다. 아직 공개되진 않았지만 AMDGPU 라는 기존의 오픈소스 드라이버에 기반한 새로운 오픈소스 드라이버를 제공할 계획이라고 합니다. 이를 통해 기존의 오픈소스 드라이버에서 지원하지 못했던 최신 그래픽 카드를 지원할 계획이라고 하니, 상당히 기대되는 부분입니다. 그리고 향후에는 상용 드라이버보다 오픈소스 드라이버에 더 집중하겠다는 얘기도 하고 있습니다. 일단 더 지켜봐야겠지만, AMD 는 오픈소스 드라이버에 대한 적극적인 지원을 통해 호환성 문제를 해결할 계획인 것 같습니다.

http://www.x.org/wiki/Events/XDC2014/XDC2014RitgerEGLNonMesa/nvidia-and-compositors.pdf
두 번째로 NVIDIA 에서 발표한 내용입니다. 일단 NVIDIA 는 AMD 와는 반대로, 상용 드라이버에서 필요한 인터페이스를 지원할 계획이라고 합니다. 그리고 더 나아가서 EGL 에서 WAYLAND, GBM, KMS 와 관련된 부분들을 표준 인터페이스로 다시 정의해서 개발하자는 얘기를 하고 있습니다. 오픈소스 쪽에서 어떻게 반응할지, 구체적으로 일이 어떻게 진행될지는 지켜봐야겠지만, 개인적으로는 나쁘진 않은 것 같습니다. 그리고 조만간 제안하는 인터페이스를 이용해서 수정한 WESTON 패치를 공개한다고 하니, 그 결과물을 보고나서 좀 더 생각을 해봐야겠습니다.

http://www.x.org/wiki/Events/XDC2014/XDC2014RitgerGLABI/presentation-xdc2014.pdf
마지막으로 NVIDIA 에서 진행하고 있는 좀 더 포괄적인 OPENGL 소프트웨어스택 통합에 대한 발표입니다. 얼마 전에 XDC 2014 행사 소개하는 글을 올리면서 개인적으로 관심이 가는 프로젝트라고 언급했었는데요, 아쉽지만 큰 진척이 있거나 크게 기대할만한 결과물이 나올꺼같진 않아보입니다. 이 프로젝트의 목적을 간단히 소개하면 위에서 언급했던 GL-API 를 제공하는 라이브러리를 하나로 통합하고, EGL-API 도 제조사와 독립적인 부분을 따로 떼서 하나의 라이브러리 형태로 공유하자는 것입니다. 그래서 하나의 시스템에서 여러 드라이버를 동시에 사용하거나, 그 이상의 일들을 해보자는 것입니다. 일단은 이 프로젝트가 계속 진행이 될지, 어떻게 진행이 될지 더 지켜봐야겠습니다.

결론적으로 DRM 드라이버 인터페이스와 EGL/KMS 가 업계 표준으로 인정받은 상황이고, 상용 드라이버 측의 지원도 문제없이 진행될꺼같습니다. 그리고 개인적으로는 ARM 쪽에서도 이런 흐름에 잘 편승했으면 하는 바램을 가져봅니다.

Advertisements

[WAYLAND] 컴포지팅 최적화 기술 소개 자료

윈도우 매니저에서는 당연히 필수이고, 위젯 엔진이나 기타 그래픽 처리가 필요한 소프트웨어에서도 거의 항상 중요한 부분을 차지하는 컴포지팅 최적화 기술에 대한 자료를 공개합니다. 일단 자료는 WAYLAND 기반의 윈도우 매니저를 기준으로 작성되었지만 대부분의 동작 원리와 적용 기술은 윈도우 매니저와는 크게 상관은 없습니다. 자세한 내용은 slideshare 에 올려놓은 자료를 참고하시고 아래는 간단히 요약한 내용입니다.

우선 컴포지팅이 무언지에 대해 간단히 소개드리겠습니다.

그림1

위 그림은 위젯 엔진과 윈도우 매니저가 동작하는 방식입니다. 위젯 엔진은 여러 위젯을 합쳐서 하나의 윈도우를 만들고, 윈도우 매니저는 여러 윈도우를 합쳐서 하나의 프레임버퍼를 만듭니다. 결국, 우리가 보는 화면은 여러 단계의 컴포지팅을 거쳐서 만들어진 결과물입니다. 이처럼 컴포지팅은 우리가 눈으로 볼 수 있는 대부분의 프로그램에서 중요한 역할을 차지하고 있습니다.

위의 그림을 한눈에 봐도 알겠지만, 컴포지팅은 결국 수많은 메모리 복사를 수반하는 작업입니다. 그래서 이를 최적화하기 위한 다양한 기술들이 오래전부터 연구/개발되어왔습니다. 가장 핵심적인 기술은 SCENE GRAPH 을 이용한 효과적인 데미지/클리핑 관리입니다. 간단히 얘기하면 변경이 필요한 부분만 갱신하고 나머지는 재활용하자는 것입니다.

그림1

위의 그림은 기본적인 데미지 관리를 통해 얻을 수 있는 효과를 보여주고 있습니다. 두 개의 윈도우가 화면에 이미(!) 존재하고, 하나의 윈도우의 특정 부분이 변경되었을 경우를 가정해봅시다. 이때 데미지 관리를 하지 않았다면 다음 프레임버퍼를 만들기 위해, 새로운 프레임버퍼를 만들고 거기에 두 개의 윈도우를 모두 복사해야합니다. 하지만 데미지 관리를 잘 하고 이전 프레임버퍼에 대한 정보를 유지하고 있었다면, 이전 프레임버퍼에 변경된 부분만 복사하여 다음 프레임버퍼를 완성할 수 있습니다. 이처럼 데미지 관리를 효과적으로 하게되면 실제로 몇 십배의 성능 차이를 볼 수 있습니다. (클리핑 기법도 상황은 다르지만 이처럼 불필요한 메모리 복사를 제거하는 효과를 볼 수 있습니다.)

마지막으로 하드웨어 가속을 이용한 컴포지팅에 대한 내용입니다. 현재 대부분의 컴포지팅 기능을 제공하는 소프트웨어는 하드웨어 가속을 사용하고 있지만, OpenGL 은 기본적으로 3D 게임을 위한 것이지 2D 컴포지팅을 위한 인터페이스가 아니기 때문에 불편하고 비효율적인 부분들이 많았습니다. 하지만 최근 이를 개선할 수 있는 다양한 확장 기능들이 OpenGL 에 추가되고 있기 때문에 이러한 기능들을 잘 이해하고 적극 활용하는 것이 굉장히 중요하다고 볼 수 있습니다.

본 자료에서 소개한 컴포지팅 최적화 기술은 특히 제한된 자원을 사용하는 임베디드/스마트 환경에서 유용하기 때문에 관련 업무를 하시는 분들은 반드시 이해하고, 필요한 부분에 적용한다면 큰 효과를 볼 수 있을 것으로 기대됩니다.

Working Towards Lower OpenGL Driver Overhead

이번 GDC 에는 개인적으로 관심이 많은 OpenGL 최적화와 리눅스 관련 발표들이 많습니다. 아래 첨부한 링크는 NVIDIA, AMD 그리고 Intel 의 GPU/OpenGL 을 연구/개발하는 대표 인력들이 최근 진행 중인 OpenGL 최적화 관련 이슈들을 같이 발표한 내용입니다.

OpenGL 최적화에서 많은 부분을 차지하는 것이 예전부터 많이 연구되어오던 API 호출을 얼마나 효과적으로 줄일 것이냐이기 때문에 전혀 새로운 내용은 거의 없지만, 관심있으신 분들은 읽어보시면 도움이 될 것 같습니다. 현존 CPU/GPU 관련 최강 회사들이 모두 뭉쳐서 발표하는 자리는 흔치 않을테니까요^^

http://www.phoronix.com/scan.php?page=news_item&px=MTYzODY

[WAYLAND] DRM 버퍼 동작 과정 (OpenGL)

지금까지는 wayland/weston 관련된 모든 내용들을 되도록이면 쉽게 이해할 수 있도록 공유메모리 버퍼를 기준으로 설명하였다. 하지만 실제 wayland/weston 을 사용할 때는 하드웨어 가속을 사용하는 것이 지극히 당연하기 때문에 오늘은 현재 wayland/weston 이 제공하는 OpenGL 기반 DRM 버퍼의 동작 과정을 살펴보도록 하겠다. 사실 공유메모리 버퍼와 DRM 버퍼의 동작 원리는 동일하다. 다만 차이는 공유메모리 버퍼는 CPU 가 관리하는 메모리를 공유하는 것이고, DRM 버퍼는 GPU 가 관리하는 메모리를 공유하는 것일 뿐이다. 하지만 문제는 GPU 의 동작 과정을 이해하기 위해 알아야 하는 소프트웨어 스택이 까다롭다는 점이다. 그래서 우선 wayland/weston 에서 DRM 버퍼 동작 과정을 이해하기 위해 알아야 하는 소프트웨어들의 구조를 살펴보도록 하겠다.

sw

위의 그림은 리눅스 환경에서 OpenGL 을 이용하기 위해 사용하는 주요 소프트웨어들의 구조이다. 일단 가장 눈에 띄는 것은 리눅스 커널에도 인텔 그래픽 카드인 i915 드라이버가 있고, mesa 에도 i915 드라이버가 있다는 것이다. 당연히 둘의 역할이 다른데, 간단히 설명하면 리눅스 커널에 있는 드라이버는 주로 GEM(Graphics Execution Manager) 이라고 하는 GPU 의 메모리를 할당하고 해제하는 역할과 KMS(Kernel-Mode Setting) 를 위해 crtc/encoder/connector 등에 직접적으로 접근하는 역할을 한다. 그리고 mesa 에 있는 드라이버는 GEM 을 통해 할당받은 버퍼에 필요한 내용을 담거나 렌더링을 요청하는 등 실제 OpenGL 의 동작 과정을 관리하는 역할을 한다고 보면 된다. 그리고 DRM 은 mesa 에서 커널에 있는 DRM 드라이버에 접근하기 위해 사용하는 일종의 wrapper 함수들의 집합이라고 보면 된다.

이제 OpenGL 의 기본적인 동작 과정에 대해 살펴보자.

rendering

우선 OpenGL 을 이용하여 무언가를 렌더링하기 위해서는 기본적으로 세 가지의 버퍼가 (이외에도 여러 가지 버퍼가 있지만 생략) 필요하다. 첫 번째 배치버퍼(batch buffer) 는 OpenGL 의 커맨드들을 순서대로 담는 버퍼이고, 두 번째 텍스쳐버퍼(texture buffer) 는 렌더링할 때 사용되는 텍스쳐를 담는 버퍼이고, 마지막 프레임버퍼(framebuffer) 는 렌더링된 결과 화면을 저장하는 버퍼이다. 세 가지 버퍼 모두 역할이 다를뿐이지 동일한 메모리를 사용한다. 이제 기본적인 OpenGL 의 렌더링 과정을 살펴보면, 일단 OpenGL 은 커맨드 기반이기 때문에 폴리곤을 그리거나(glVertex) 폴리곤에 텍스쳐를 붙이거나 광원을 조절하거나 하는 등의 모든 일은 커맨드 형태로 배치버퍼에 순서대로 저장된다. 그리고 텍스쳐버퍼에 필요한 이미지를 저장하는(glTexImage) 등의 렌더링에 필요한 준비 작업이 모두 끝나고 나면 마지막으로 한번에 렌더링 요청을(eglSwapBuffers) 하게 된다. 렌더링하는 과정은 mesa 와 리눅스 커널 드라이버에서 GPU 에게 배치버퍼와 텍스쳐버퍼, 그리고 프레임버퍼의 메모리 주소와 같은 필요한 정보만 GPU 에게 잘 전달해주면 나머지는 GPU 가 알아서 처리해준다. 그리고 렌더링이 완료되면 프레임버퍼에는 최종 결과 화면이 담겨져있게 된다. 하지만 여기서 끝이 아니고, 현재 모니터가 출력하고 있는 화면을 방금 렌더링한 프레임버퍼로 변경해주어야 한다. (그래서 기본적으로 더블버퍼링을 한다) 최종적으로 이 작업까지 모두 끝나고나면 실제 렌더링된 화면이 우리의 모니터에 나타나게 된다.

지금까지 리눅스 환경에서 OpenGL 의 기본적인 동작 과정을 살펴보았다. 이제 본격적으로 wayland/weston 에서 DRM 버퍼를 사용하는 과정에 대해 살펴보도록 하겠다.

rendering

위 그림은 클라이언트가 OpenGL 로 렌더링한 결과 화면을 weston 이 받아서 화면에 그리는 과정을 간략하게 나타낸 것이다. 우선 클라이언트는 현재 mesa 가 제공하는 wayland 를 백엔드로 하는 EGL window/surface 와 OpenGL 을 위한 컨텍스트를 생성하고 필요한 렌더링 준비작업을 수행한다. 그리고 eglSwapBuffers() 함수를 이용하여 실제로 렌더링을 하게 되면 client-side mesa 에서 클라이언트가 요청한 프레임버퍼에 대한 핸들(local name: 리눅스 커널이 제공하는 해당 GPU 내의 메모리 영역을 구분해주는 아이디라고 보면 된다) 을 server-side mesa 로 전달한다. (동일한 mesa 라이브러리에 클라이언트와 weston 이 사용하는 함수가 모두 들어있다.) 그러면 server-side mesa 에서는 전달받은 핸들을 이용하여 클라이언트가 사용 중인 프레임버퍼에 접근할 수 있는 wl_drm_buffer 를 생성한다. (공유메모리 버퍼를 사용할 때는 이와 유사한 일을 wayland 가 처리한다.) 여기까지 완료되면 일단 클라이언트가 사용하는 프레임버퍼에 weston 이 접근할 수 있는 준비는 끝난 것이다. 그리고나서 클라이언트가 렌더링을 하고 나면 최종 이미지가 프레임버퍼에 저장되고, 렌더링이 완료된 버퍼(wl_buffer) 를 원하는 서페이스(wl_surface) 에 attach/damage/commit 하는 과정은 client-side mesa 가 알아서 처리해준다.

위에서 설명한 과정은 클라이언트가 렌더링한 결과 화면을 weston 이 전달받는 과정이고, 이제 weston 에서 (컴포지팅된) 최종 화면을 만들어내는 과정을 살펴보자. 이 과정은 생각보다 단순한데, weston 은 위에서 클라이언트가 렌더링한 결과 화면인 프레임버퍼를 텍스쳐로 사용하여 서페이스(wl_surface) 의 위치와 크기에 맞는 폴리곤을 생성하면 된다. 물론 여러 서페이스가 겹치기 때문에 적절하게 잘려진 폴리곤을 생성하는 과정과 그에 맞는 텍스쳐 좌표를 지정하는 것은 필수이다. 그리고 최종적으로 eglSwapBuffers() 함수를 이용하여 렌더링하면 최종 결과 화면이 생성되고, 이 결과 화면을 실제 모니터에 출력하면 된다. (클라이언트가 사용한 eglSwapBuffers() 함수는 백엔드가 wayland 이기 때문에 위에서 설명한 과정을 거친 것이고, weston 이 사용한 eglSwapBuffers() 함수는 백엔드가 DRM 이기 때문에 클라이언트와는 다른 과정을 거치게 된다.)

지금까지 wayland/weston 에서 DRM 버퍼의 동작 과정을 살펴보았다. 클라이언트와 weston 외에 mesa 가 하는 일이 많고 복잡하기 때문에 당장은 이해하기 어렵겠지만, 일단은 클라이언트가 렌더링한 프레임버퍼를 weston 이 전달받고, 이를 텍스쳐로 사용하여 최종 화면을 렌더링한다는 것 정도만 기억해두면 될것같다.