태그 보관물: WAYLAND

[WAYLAND] HARDWARE COMPOSER (in ANDROID)

오늘은 안드로이드에서 HARDWARE COMPOSER (HWC) 라고 부르는 기능에 대해 소개하고자 한다. 사실 이 기능은 안드로이드 3.0 에서 소개된 기능이긴 하지만, 유사한 기능이 데스크탑에서 꽤 오래전부터 사용되어 왔었고, 현재 WESTON 에도 유사한 기능이 들어가있다. 암튼 이게 어떤 역할을 하고, 어떤 장점을 가지는지 살펴보자.

hwc0

위 그림은 HWC 가 없는 일반적인 하드웨어 가속을 이용한 렌더링 과정이다. 하나의 배경화면과 두 개의 윈도우가 있고, 각각 텍스처를 하나씩 할당받아 현재의 위치에 렌더링된다. 렌더링된 프레임버퍼는 HDMI 를 통해 디스플레이로 전송되어 결국 화면에 나타나게 되는데, 사실 이 정도만 해도 충분히 나쁘지 않은 결과를 보여준다. 하드웨어 가속(GPU)을 사용하기 때문에 프로세서(CPU)의 부담을 줄일 수 있고, 또한 충분히 빠르고 효과적이다. 하지만, GPU로 CPU의 역할을 대체하는 것만이 최선일까? 결국 GPU 또한 성능의 한계가 있고, 많은 전력을 사용하는 장치일뿐이다. 그래서 GPU를 보다 효과적으로 사용하기 위한 다양한 연구가 진행 중이고, 그 중에 비교적 작은 노력으로 작지 않은 효과를 볼 수 있는 방법 중의 하나가 바로 HWC 이다. 아래 그림은 HWC 와 하드웨어 가속을 이용하여 렌더링하는 과정을 나타내고 있다.hwc1

앞의 예제와 동일하게 하나의 배경화면과 두 개의 윈도우가 있지만, 배경화면을 제외한 두 개의 윈도우만 하드웨어 가속을 이용하여 렌더링하고 있다. 이럴 경우 우리가 얻을 수 있는 장점은 무엇일까? 예를 들어, 배경화면에 초당 60 프레임의 애니메이션이 들어가있는 경우를 상상해보자. 만약, HWC 가 없다면 전체화면을 덮고 있는 배경화면이 변경되었기 때문에, 프레임버퍼에 배경화면을 덮어씌우고 그 위에 윈도우 두 개를 다시 덮어씌워야 원하는 결과를 얻을 수 있다. 이런 과정을 GPU 가 초당 60번씩 해야한다. 하지만, 아래 그림처럼 HWC 를 사용하는 경우라면 어떨까? 배경화면만 변경되고 두 개의 윈도우는 변경사항이 없기 때문에 GPU 는 프레임버퍼를 다시 렌더링하지 않아도 되고, 배경화면만 HDMI 를 통해 디스플레이로 전송하면 동일한 결과를 얻을 수 있다. 즉, GPU 가 했던 컴포지팅의 일부를 디스플레이가 제공하는 오버레이 기능으로 대체함으로써 GPU 의 사용량을 극단적으로 줄일 수 있게 된 것이다. 그렇다면 원하는 모든 컴포넌트(배경화면, 윈도우, 마우스 포인터, …)에 독립적인 오버레이를 지정하면 더 좋지 않을까? 여기에는 다음과 같은 몇 가지 제약 사항이 있다.

  • 첫 번째는 디스플레이가 지원하는 오버레이의 수가 제한되어 있다. (약 2~4개 정도이지만, 대부분 하나는 마우스 포인터를 위해 할당해서 사용되고 있다.)
  • 두 번째는 회전과 같은 변형을 지원하지 않는다. 만약에 특정 윈도우가 기울어져 있다면 현재의 디스플레이가 제공하는 오버레이 기능은 사용하기 힘들다.
  • 세 번째는 중간에 끼어있는 컴포넌트는 오버레이를 사용할 수 없다. 예를 들어, 배경화면과 앞에 있는 윈도우가 하드웨어 가속을 사용한다면, 뒤에 있는 윈도우를 오버레이로 지정해서 동일한 결과를 얻기는 어려워진다.

이 외에도 여러 가지 제약사항이 더 있을 수 있겠지만, 앞으로 HWC 기능이 더 활발히 사용된다면 디스플레이 쪽에 더 유용한 기능이 들어갈 수 있지 않을까 기대해본다.

마지막으로 정리하면, 우리가 앞으로 기억해야 가장 중요한 사실은 기존에 CPU 와 GPU 가 나눠서 하던 컴포지팅에 디스플레이까지 참여하게 되었다는 것이다. 이는 컴포지팅 과정을 좀 더 복잡하게 만들겠지만, 그만큼 더 효과적으로 만들 수 있을 것으로 기대된다. 이제 플랫폼 개발자들은 CPU, GPU 그리고 디스플레이의 장단점을 파악해 보다 효과적인 컴포지팅 기술을 연구/개발해야 할 것 같다.

Advertisements

[WAYLAND] CSD + SSD <= DWD?!

최근 KDE 측에서 매우(!) 흥미로운 기술을 하나 공개했다. 바로 DWD(Dynamic Window Decorations) 라는 기술인데, 오늘은 이 기술에 대해 간단히 살펴보고자 한다.

http://kver.wordpress.com/2014/10/25/presenting-dwd-a-candidate-for-kde-window-decorations/

이전 글들에서 WAYLAND 와 X11 을 비교하면서 가끔 언급했었지만, 윈도우 데코레이션(Window Decorations)은 최소/최대/종료 버튼이 있는 윈도우 프레임을 그리는 일을 의미하고, CSD(Client-Side Decorations)는 클라이언트가 윈도우 프레임을 그리는 방식, 그리고 SSD(Server-Side Decorations)는 서버가 윈도우 프레임을 그리는 방식을 의미한다. 각각의 장단점에 대해 간단히 정리해보면 다음과 같다.

  • SSD 는 서버에서 직접 그리는 작업을 해야하기 때문에 다양한 폰트/벡터/아이콘/… 렌더링을 지원해야하는 문제가 발생한다. 반면에, CSD 는 클라이언트가 모든 것을 그리기 때문에 상대적으로 서버를 가볍게 유지할 수 있다. (WAYLAND 의 탄생 목적이 서버의 경량화이기 때문에 당연히 WAYLAND 는 CSD 를 선호한다.)
  • CSD 는 윈도우 프레임을 클라이언트가 그리기 때문에 최소/최대/종료 이벤트를 클라이언트가 확인해서 서버에게 요청해야 한다. 그래서 클라이언트가 어떤 오류에 의해 종료 이벤트를 처리하지 못 하면 정상적인 종료가 힘들어진다. (SSD 는 클라이언트와 상관없이 종료 이벤트를 처리할 수 있기 때문에 이러한 문제는 발생하지 않는다.)
  • SSD 는 서버에서 모든 윈도우의 프레임을 그리기 때문에 일관성을 유지할 수 있다. 하지만 CSD 는 각종 위젯 엔진이나 어플리케이션들이 자발적으로 윈도우 프레임을 일관성있게 유지해야 한다.

이러한 장단점들을 가지는 CSD 와 SSD 에 대한 갑론을박은 최근 X11 에서 빠르게 WAYLAND 로 전환되면서 더해지고 있었는데, 최근 KDE 측에서 상당히 획기적인 아이디어를 제안한 것이다. 사실 아이디어 자체는 매우 간단하다. 하지만, CSD 와 SSD 의 장점을 결합한 새로운 윈도우 데코레이션 기법이라는 점을 훨씬 넘어서는, 다양한 응용이 가능한 기법이 탄생했다는 사실에 다들 놀라워하고 있다. 원리는 간단하다. 예를 들면, 클라이언트는 최소/최대/종료 버튼으로 사용할 아이콘을 서버에 등록하고, 서버는 이 아이콘들을 원하는대로 배치해서 사용할 수 있다. 즉, 그리는 것은 CSD 처럼 클라이언트가 하지만, 레이아웃과 이벤트 처리는 SSD 처럼 서버가 하는 것이다. 이것만으로도 사실 상당히 많은 장점들을 가진다. 하지만, 여기에서 끝이 아니고 새로운 응용 방법들이 하나둘씩 제안되고 있다.

multiformfactor

위의 그림을 자세히 보면, 어플리케이션의 프로그레스바와 종료 버튼 등이 윈도우 프레임과 패널, 그리고 스마트폰 타입의 레이아웃에 그대로 적용되는 것을 볼 수 있다. 이는, 클라이언트가 해당 프로그레스바와 종료 버튼을 서버에 등록해놓으면 서버가 필요에 따라 다양한 형태로 사용할 수 있다는 것이다. 그리고 더 나아가면, 클라이언트는 개별 컴포넌트들을 그리는 역할을 하고, 서버는 환경에 따라/필요에 따라 해당 컴포넌트들을 적절히 배치할 수 있게 된다. 아직 초기 제안 수준이기 때문에 DWD 라는 아이디어가 어디에서 어떻게 쓰일지는 알 수 없다. 하지만 상당히 획기적인 아이디어이기 때문에 현재의 윈도우 매니저들에게 작든, 크든 영향을 끼칠거라는 점은 명백한 것 같다. 또한, 향후 컴퓨팅 환경이 데스크탑 뿐 아니라, 스마트폰, 스마트TV, 스마트카 등 크기와 모양이 다양해지는 점을 감안해보면, 클라이언트 측에서 처리해야했던 레이아웃에 대한 부담을 서버가 적절히 가져갈 수 있을 것으로 기대된다.

[WAYLAND] GPU 동작 원리 (렌더링 & 동기화)

오늘은 GPU 의 가장 기본적인 역할인 렌더링과 관련된 내용을 살펴보고자 한다. 특히, OPENGL 을 사용하는 어플리케이션과 윈도우 매니저, 그리고 GPU 간의 동기화가 어떻게 이루어지는지에 대해 초점을 맞춰서 설명할 계획이다. 그럼 우선 기본적인 용어 몇 가지부터 살펴보자. (이후부터 모든 설명은 TESLA 아키텍처 이후의 NVIDIA 그래픽 카드를 기준으로 한다.)

첫 번째로 알아야 할 것은 채널(channel)이다. 일반적인 CPU 는 코드를 메모리에 올려놓고 PC(Program Counter) 레지스터를 이용하여 명령을 순차적으로 수행한다. 하지만 GPU 는 채널이라는걸 이용하는데, 이는 일종의 링(ring) 버퍼라고 생각하면 된다. 즉, 3D 어플리케이션은 채널의 링버퍼에 명령어를 주입하고, GPU 는 채널의 링버퍼에서 명령어를 읽어와서 실행하는 과정을 반복적으로 수행하는 것이다. 채널의 링버퍼에 들어가는 명령어에는 OPENGL 에서 제공하는 기본 명령어들(glVertex, glColor, …)과 렌더링에 관련된 다양한 명령어들이 존재한다.

두 번째로 알아야 할 것은 버퍼(buffer)이다. 기본적인 버퍼에는 폴리곤의 표면에 그려지는 그림을 저장하는 텍스처와 렌더링한 결과물을 저장하는 프레임버퍼가 있고, 이외에도 버텍스를 저장하는 버퍼, 인덱스를 저장하는 버퍼 등 다양한 버퍼들이 있다.

마지막으로 알아야 할 것은 펜스(fence)이다. 위의 두 가지는 들어본 적이 있을 가능성이 높지만, 펜스는 아마 처음 들어본 사람이 많을 것이다. 이는 간단히 얘기하면, 동기화를 위한 일종의 세마포어라고 보면 된다. 사실 따지고 보면, 스핀락(spinlock) 이라고 보는 것이 더 정확한 표현인것 같다. 즉, 하나의 변수를 미리 지정해놓고, 한 채널에서는 작업이 완료되면 해당 변수를 특정 값으로 설정하고, 다른 채널에서는 해당 변수의 값이 특정 값이 될때까지 반복적으로 확인하면서 기다리는 것이다. GPU 의 특성상, 코어가 많고 운영체제와 같은 관리 체계가 없는 것을 감안하면 나름 최선의 선택이라고 볼 수 있다.

그럼 간단한 용어 설명은 여기까지 하도록 하고, 기본적인 렌더링 과정부터 살펴보도록 하자.

fence1

위의 그림은 일반적으로 하드웨어 가속을 이용하는 소프트웨어에서 프레임버퍼 렌더링(swapbuffer)과 디스플레이 동기화(pageflip)를 수행하는 과정을 나타내고 있다. 우선 그림에서 보이는 몇 가지 용어들에 대해 추가로 설명하면, 세마포어(semaphore)는 펜스(fence)에서 사용하는 변수를 의미하고, 펜스에 EMIT 이 붙어있는 것은 세마포어에 특정 값을 설정하는 역할을 하고, 펜스에 SYNC 가 붙어있는 것은 세마포어가 특정 값인지를 확인하면서 기다리는 역할을 한다. 그리고 오브젝트는 텍스처와 프레임버퍼만 표시해두었는데, 모든 오브젝트는 특정 펜스와 연관되어 있다. 이유는, 예를 들어, 프레임버퍼로 사용되는 오브젝트는 렌더링이 완료되어야만 유효해지기 때문이다. (이외에도 오브젝트에 펜스를 연결시켜두는 이유는 여러 가지가 있다.) 이러한 이유로 렌더링이 완료되었음을 나타내는 펜스를 미리 만들어두고, 프레임버퍼로 사용되는 오브젝트가 해당 펜스를 참조하게 해놓은 것이다. 그리고 다른 채널에서 해당 오브젝트를 사용할 때는 오브젝트가 참조하는 펜스를 이용하여 동기화(SYNC)를 하면 아무 문제없이 사용할 수 있게 된다.

그럼 이제 그림을 보면서 동작 과정을 살펴보도록 하자. OPENGL 어플리케이션에서 렌더링을 하기 위해 두 개의 텍스처 오브젝트와 렌더링과 관련된 명령어들을 준비한 다음, MESA/DRM 을 통해 렌더링을 요청한다. 그러면 MESA/DRM 에서는 채널을 하나 할당받은 다음, 우선 렌더링에 사용할 두 개의 오브젝트가 참조하는 펜스를 SYNC 하는 명령어를 집어넣는다. 이는 해당 오브젝트들이 다른 목적에 의해 작업이 아직 완료되지 않았을 수도 있기 때문에 반드시 필요한 과정이다. 그리고나서 렌더링에 필요한 명령어들을 순서대로 집어넣고, 마지막으로 프레임버퍼 오브젝트에서 참조하게 될 펜스를 만든 다음, 이를 EMIT 하는 명령어를 집어넣는다. 여기서 한 가지 명심할 것은 채널에 명령어를 집어넣는 것은 CPU 에서 처리하는 것이고, 실제 채널에 있는 명령어를 수행하는 것은 CPU 와 상관없이 GPU 에서 비동기로 수행하게 된다는 점이다. 즉, 언젠가 GPU 가 해당 채널에 있는 명령어를 처리하게 되면 맨 앞에 있는 펜스를 SYNC 하는 부분부터, 렌더링과 관련된 명령어들, 그리고 마지막에 있는 펜스에 EMIT 하는 부분까지 순서대로 수행한다는 말이다.

그렇다면 디스플레이 동기화는 어떻게 처리할까? 이것 또한 렌더링과 유사한 과정을 거친다. OPENGL 어플리케이션에서 디스플레이 동기화(pageflip)를 요청하면 MESA/DRM 에서는 해당 요청을 처리할 채널을 하나 할당받은 다음, 화면에 출력할 프레임버퍼 오브젝트가 참조하는 펜스를 SYNC 하는 명령어를 집어넣는다. 이를 통해 해당 프레임버퍼를 위한 렌더링이 완료된 다음, 이후의 요청이 처리되어 안전하게 프레임버퍼를 화면에 표시할 수 있게 되는 것이다. 그래서 해당 펜스를 SYNC 하는 명령어를 넣은 다음에 실제 VBLANK 에 맞춰서 프레임버퍼를 교체하는 명령어들을 집어넣게 되면, CPU 의 할일은 끝나게 된다. 즉, 프레임버퍼 렌더링부터 디스플레이 동기화까지 CPU 입장에서는 필요한 명령어와 펜스만 잘 설정해주면 GPU 에 의해 정확한 순서대로 작업이 처리되는 것이다.

이제 마지막으로 윈도우 환경에서 클라이언트와 서버가 동시에 하드웨어 가속을 사용하는 과정을 간단히 살펴보자.

fence2

위의 그림을 보면, 클라이언트는 프레임버퍼 렌더링 요청을 한 후, 바로 서버에게 해당 버퍼를 전달한다. (wl_surface_commit) 그리고 서버는 클라이언트가 요청한 프레임버퍼 또한 일반적인 오브젝트이기 때문에 해당 오브젝트가 참조하는 펜스를 SYNC 한 후에 앞에서 계속 언급했던 것과 동일한 과정을 수행한다. 즉, 클라이언트가 요청한 프레임버퍼 오브젝트의 펜스는 클라이언트가 요청한 렌더링이 완료된 후에 EMIT 되기 때문에 아무 문제없이 렌더링이 완료된 프레임버퍼가 화면에 출력된다.

여기까지 CPU 와 GPU 가 어떤 방식으로 프레임버퍼를 렌더링하고 동기화하는지에 대해 살펴보았다. 지난 글에서 소개했던 메모리 및 주소 공간 관리처럼 GPU 는 CPU 와 비슷한 듯하면서도 상당히 다른 방식으로 동작한다. 가장 큰 이유는 GPU 는 CPU 에 의해 동작하는 수동적인 장치라는 것이다. 그리고 매번 CPU 가 동일한 요청을 반복해서 보내지 않는다는 것이다. 왜냐하면 기본적으로는 매번 다른 화면이 모니터에 표시되기 때문이다. 이러한 차이점들을 잘 이해하고 생각을 정리해본다면 GPU 가 동작하는 방식에 대해 이해하는 것이 좀 더 쉬울 것 같다.

[스터디-공지] WAYLAND 기반 윈도우 매니저 동작 원리 이해 (3주차)

이번 스터디에서는 윈도우 매니저의 입력 장치 관련된 내용을 진행하려고 합니다. 스터디에서 다룰 구체적인 내용은 아래와 같습니다.

  • 윈도우 매니저 입력 : 기본 동작 과정 (포커스, …)
  • 그랩 인터페이스 : 윈도우 위치/크기 변경 과정
  • 데이터 인터페이스 : 드래그&드롭, 셀렉션(클립보드), …
  • 가상 키보드/한글 입력 동작 과정
  • 세션 관리 : TTY(VT), SEAT, SYSTEMD/LOGIND, …

그리고 세미나 때 사용할 자료를 첨부하였으니 관심있으신 분들은 참고하시기 바랍니다.
http://www.slideshare.net/nemoux/3-39954418

세부 모임 공지는 아래와 같습니다.

일시 : 2014년 11월 1일 (토요일) 오후 2시 ~ 4시
장소 : 성균관대학교 자연과학캠퍼스 제 1공학과 21515호 (1호선 성균관대역)
연락 : nemoux00@gmail.com (페이스북 그룹 : https://www.facebook.com/groups/uxcoding/)

[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 쪽에서도 이런 흐름에 잘 편승했으면 하는 바램을 가져봅니다.

[WAYLAND] DRM 장치 관리 (LEGACY vs RENDER+CONTROL)

오늘은 DRM 장치 관리 방식에 대해 소개하려고 한다. 우선, GPU 가 제공 하는 기능은 크게 두 가지로 나뉜다. 우리가 일반적으로 하드웨어 가속이라고 표현하는 렌더링과 GPGPU 에 사용되는 기능과 PAGE_FLIP 이나 CRTC/PLANE 을 다루는 디스플레이 관련 기능이다. ARM 의 경우에는 이 두 가지가 서로 다른 장치로 분리되어있지만, 데스크탑의 경우는 보통 하나의 그래픽 카드가 두 가지 기능 모두를 제공한다. 그래서 현재 DRM 은 이 두 가지 기능을 하나의 DRM 장치 파일에서 제공하게 되었고, 이로 인해 여러 가지 문제가 발생하고 있다. 이를 해결하기 위해 나온 것이 바로 하드웨어 가속 관련 기능을 담당하는 장치 파일과 디스플레이 관련 기능을 담당하는 장치 파일로 나누는 것이다. 다행히 기존의 DRM 아키텍처에 대한 큰 수정없이 작업이 진행 중이고, 앞으로는 다양한 어플리케이션이 편리하게 GPU 를 사용할 수 있게 될 것이다.

legacy

위의 그림은 전통적인 방식의 DRM 장치 접근 과정이다. 우선, GPU 를 사용하기 위해서는 윈도우 매니저가 마스터가 되어 DRM 을 관리해야 한다. 마스터는 말그대로 DRM 을 통해 GPU 의 모든 기능을 관리할 수 있는 권한이라고 보면 된다. 그래서 하나의 마스터만이 존재할 수 있고, 마스터 권한을 얻기 위해서는 ADMIN 권한이 필요하다. 그리고 클라이언트는 윈도우 매니저와 마찬가지로 LEGACY NODE(card0) 를 사용하지만, 매직 코드를 할당받아서 이를 마스터인 윈도우 매니저에게 인증을 받아야만 DRM 을 통해 GPU 의 자원을 사용할 수 있게 된다. 즉, 마스터인 윈도우 매니저가 없으면 어떤 어플리케이션도 GPU 를 사용할 수 없다는 얘기다. 그렇다면 윈도우 매니저가 없는 서버 환경에서는 GPGPU 를 위해 어떻게 GPU 를 사용할까? 강제로 누군가가 마스터가 되어 GPGPU 를 사용하고자 하는 어플리케이션을 인증해주던가 뭔가 다른 방법을 찾아야 할 것이다. 그래서 이를 해결하기 위해 나온 것이 하드웨어 가속 관련 기능과 디스플레이 관련 기능을 서로 다른 장치 파일로 나누는 것이다.

우선 왜 이런 접근 방식을 사용하는지에 대해 간단히 생각해보자. 기본 컨셉은 이렇다. 하드웨어 가속 기능은 공유가 가능하기 때문에 굳이 루트 권한이 없더라도 누구든지 적당히(!) 쓸 수 있게 하겠다는 것이다. 이유는 여러 어플리케이션이 동시에 하드웨어 가속을 이용한다고 하더라도 경쟁에 의한 오버헤드로 결과가 조금 더 느리게 나올 뿐이지 결과 자체에는 영향을 주지 않기 때문이다. 하지만 디스플레이 관련 기능은 공유가 불가능하기 때문에 좀 더 신경써서 관리해야 한다. (두 개의 어플리케이션이 동시에 디스플레이를 갱신한다고 생각해보자. 화면이 왔다갔다 난리가 날 것이다.)

render+control

위의 그림을 보면 알겠지만 기존보다 훨씬 단순해졌다. 우선, 하나의 장치 파일(LEGACY NODE)로 관리되던 DRM 이 하드웨어 가속 관련된 기능을 제공하는 RENDER NODE 와 디스플레이 관련된 기능을 제공하는 CONTROL(or MODESET) NODE 로 나누어졌다. 그래서 디스플레이를 관리하는 윈도우 매니저는 CONTROL NODE 와 RENDER NODE 를 동시에 사용하고, 일반적인 윈도우 클라이언트와 GPGPU 를 사용하는 어플리케이션은 RENDER NODE 만을 사용하면 된다. 윈도우 클라이언트는 기본적인 렌더링 기능과 PRIME/DMA-BUF 관련된 기능까지 사용할 수 있기 때문에 필요한 것을 하드웨어 가속을 이용하여 렌더링한 다음, PRIME 기능을 이용하여 결과물을 윈도우 매니저에 전달할 수 있다. 또한 윈도우 매니저가 없더라도 RENDER NODE 를 사용하는데는 아무런 제약 사항이 없기 때문에 GPGPU 를 사용하는 것이 한결 수월해졌다.

그리고 이 외에도 기대되는 기능이 몇 가지가 있는데, 그 중에 하나는 하나의 GPU 에서 여러 개의 CONTROL NODE 를 동시에 지원하는 것이다. 이게 뭐냐하면 일반적으로 GPU 는 두 개 이상의 디스플레이를 지원한다. 하지만 지금까지는 하나의 마스터만 존재할 수 있기 때문에 하나의 윈도우 매니저가 모든 디스플레이를 관리해야 했다. 이를 해결하기 위해 CONTROL NODE 를 단순히 GPU 별로 생성하지 말고, GPU 의 CRTC 별로도 생성할 수 있게 하자는 얘기가 나오고 있다. 이렇게 되면 두 개의 윈도우 매니저를 띄워서 하나의 GPU 에 연결된 두 개의 CRTC 를 각자 관리할 수 있게 되는 것이다. 사실, 꼭 필요한 기능은 아니어서 작업이 진행되고 있는 것 같진 않은데, 어찌됐던 이렇게까지 DRM 을 유연하게 사용할 수 있는 방법에 대한 얘기가 오고가고 있다는 것이다.

마지막으로 해당 기능은 올해 초에 리눅스 커널에 정식으로 반영이 되었다. 하지만, 아직은 대부분의 소프트웨어가 기존의 방식을 그대로 사용하고 있기 때문에 LEGACY NODE 와 RENDER/CONTROL NODE 를 동시에 지원하고 있다.

[WAYLAND] 가상 터미널과 세션 관리 (SYSVINIT+VT vs SYSTEMD+CONSOLED)

일반적으로 리눅스는 부팅을 하면 6개의 가상 터미널을 생성하고, 우리는 ALT+F[1-6] 키를 이용하여 가상 터미널을 이동하면서 사용한다. 오늘은 전통적인 SYSVINIT 과 VT 기반의 가상 터미널이 어떻게 동작하는지, 그리고 어떤 문제를 가지고 있는지와 이에 대한 대안으로 등장한 SYSTEMD 와 CONSOLED 에 대해 알아보자.

sysvinit+vt

위의 그림은 SYSVINIT 과 VT 기반의 가상 터미널 동작 과정이다. 우선 VT(Virtual Terminal) 는 리눅스 커널이 제공하는 가상 터미널 에뮬레이터이다. 간단히 얘기하면 모든 입력 장치(event0/1)로부터의 입력을 활성화된 가상 터미널(tty0)로 전달해주고, 활성화된 가상 터미널로부터의 출력을 하나의 출력 장치(card0)로 전달해주는 역할을 한다. 그리고 각각의 가상 터미널은 /dev/tty[1-6] 장치 파일을 통해 접근이 가능하다. 즉, SYSVINIT 을 통해 /sbin/getty 를 tty[1-6] 에 연결해놓으면 우리가 일반적으로 사용하는 리눅스 환경처럼 6개의 가상 터미널이 로그인 준비를 하게 된다는 말이다. getty 의 기본적인 역할은 할당받은 tty 로 표준입력(0) 과 표준출력(1)/에러(2) 파일디스크립터를 준비하고, “login:” 프롬프트를 출력한 후에 사용자 입력을 대기한다. 그리고 사용자가 usename 을 입력하면 해당 username 을 인자로 하여 /bin/login 프로그램을 실행(exec)한다. (이 때, fork 는 하지 않고 getty 가 미리 준비해둔 표준 입출력을 그대로 사용한다.) 그리고 login 은 사용자로부터 password 를 입력받은 후에, 틀리면 해당 프로세스를 종료하여 SYSVINIT 에 의해 다시 getty 가 실행되도록 하고, 맞으면 쉘(bash)을 실행(exec)한다. 이러한 과정을 거쳐 우리는 가상 터미널에서 로그인하여 쉘을 이용할 수 있게 된다. 그리고 가상 터미널을 교체하는 방법은 우리에게 매우 익숙한 ALT+F[1-6] 키를 입력하면 리눅스 커널의 VT 가 가로채서 해당 번호의 가상 터미널을 활성화하게 된다.

이러한 SYSVINIT 과 VT 는 굉장히 오랜 세월 동안 사용되어오던 방식으로 현재는 여러 가지 문제에 봉착하여 한계점을 드러내고 있다. 대표적으로 SYSVINIT 은 스크립트 기반이라는 점과 직렬/동기 방식의 초기화 과정으로 인해 부팅 속도 저하라는 한계점을 가지고 있고, VT 는 하나의 SEAT 만을 지원하고 커널에 터미널 에뮬레이션 관련 코드가 모두 포함되어 유지/보수를 어렵게 만드는 문제가 있다. 또한 VT 를 이용한 시그널 기반의 세션 교체는 예전부터 심각한 문제를 발생시켜왔다. 이는 특히 SYSVINIT 과 VT 기반의 X 그래픽 환경에서 많은 어려움을 유발시킨다.

sysvinit+x

위의 그림은 기본적인 X 그래픽 환경의 동작 과정이다. getty 를 기반으로 하는 텍스트 쉘 환경과는 다르게 X 그래픽 환경은 입출력 장치에 직접 접근할 필요가 있다. (그림이 약간 애매하게 그려져있는데, event0/1 과 card0/1 은 X 서버에 직접 연결되어있고, 그림에서는 X 서버가 tty0 에 속해있다는 의미로 받아들이면 되겠다.) 그래서 X 서버는 DRM 과 EVDEV 를 통해 입출력 장치를 직접 제어하게 된다. 여기서 문제는 사실 여러 가지가 겹쳐있는데 우선, 다른 가상 터미널로 이동할 때 X 서버가 직접 DRM 과 EVDEV 에 대한 접근을 내려놓아야 한다는 것이다. 이를 위해 커널의 VT 는 가상 터미널을 교체하는 과정에서 X 서버에게 시그널을 보내는데, 만약에 X 서버가 이를 제대로 처리하지 못 하면 시스템은 먹통이 되어버린다.

이 외에도 SYSVINIT 과 VT 는 여러 가지 문제를 가지고 있고, 이를 해결하기 위해 나온 것이 바로 SYSTEMD 와 CONSOLED 이다. 사실 SYSTEMD 는 SYSVINIT 을 대체하기 위해 나온 것이고, CONSOLED 는 커널 레벨의 터미널 에뮬레이션(VT)을 유저 레벨에서 구현한 것이라고 보면 된다. 하지만, SYSTEMD 도 아직 한창 작업 및 표준화 중이고, CONSOLED 는 얼마 전에 공개되었기 때문에 아직 동작이 명확하지 않은 부분도 있고, 기존의 SYSVINIT 과 VT 와 혼용해서 사용하는 경우도 많다. 그래서 오늘은 기본적인 이해를 위해 꼭 필요한 부분만 간단히 설명하도록 하겠다.

systemd+consoled

우선 SYSTEMD 에서 가장 중요한 부분 중에 하나인 LOGIND 에 대해 알아보자. 기본적으로 SYSTEMD 는 모든 서비스(세션)가 직접 장치 파일을 여는 것을 금지하고 있다. 기본적으로 장치 파일을 열기 위해서는 D-BUS 를 통해 LOGIND 에 요청하고, LOGIND 는 해당 장치 파일을 대신 열고 해당 세션에 등록한 후, 장치 파일을 요청한 서비스에게 전달해준다. 이렇게 하는 가장 큰 목적은 LOGIND 가 모든 장치 파일에 대한 제어권을 가지기 위해서이다. 그래서 기존과 달리 LOGIND 에서는 가상 터미널을 교체할 때 시그널을 전달할 필요없이 해당 세션에서 사용 중인 장치 파일을 직접 중지시킬 수 있다. (이를 위한 인터페이스는 DRM 과 EVDEV 에서 이미 제공하고 있다.) 이러한 기능 덕분에 X 서버가 다운되거나 다른 문제가 발생하더라도 시스템 전체가 먹통이 되는 일을 막을 수 있게 된다.

그리고 CONSOLED 는 위에서 간단히 언급했던 대로 터미널 에뮬레이터이다. 그래서 터미널에서 사용하는 입출력 장치를 관리하기 위해 입력은 EVDEV 를, 출력은 DRM 을 사용한다. (당연히 해당 장치 파일은 LOGIND 를 통해 열게 된다.) 그리고 쉘과의 통신을 위해서는 PTY 를 사용하는데, 이는 간단히 설명하면, 기존의 TTY 를 이용하는 쉘은 쉘의 표준 입출력이 커널에 있는 VT 와 바로 연결되어 있지만, CONSOLED 에서 사용하는 쉘은 쉘의 표준 입출력이 프로세스 형태로 동작하는 CONSOLED 에 연결되어있기 때문에 쉘과 CONSOLED 를 위한 IPC 로 사용되는 것이라고 보면 된다. 이는 기존에도 많이 사용되던 방식으로, 대표적인 예가 바로 SSH 와 GNOME-TERMINAL 이다. SSH 와 GNOME-TERMINAL 에서도 쉘과의 통신을 위해 PTY 를 사용한다.

그렇다면 기존의 커널의 VT 에서 처리해주던 가상 터미널 이동은 어떻게 할까? 기존보다 훨씬 단순해졌는데, 기본적인 과정은 ALT+F[1-6] 키를 CONSOLED 가 받아서 D-BUS 로 SwitchTo 메소드를 호출한다. 그러면 LOGIND 가 이 메소드를 받아서 앞에서 잠깐 설명했던 것처럼 이전 세션에서 사용 중이던 모든 장치 파일을 중지시키고, 다음 세션에서 사용할 모든 장치 파일은 재시작시킨다. 이전보다 훨씬 간단하면서도 강력한 제어가 가능해진 것이다.

지금까지 SYSVINIT 과 VT, 그리고 SYSTEMD 와 CONSOLED 에 대해 설명하였다. 현재 많은 배포판과 프로젝트들이 SYSTEMD 를 적용하기 위한 작업을 진행하고 있지만, X11 에서 WAYLAND 로 넘어가는 것처럼 수많은 일들이 걸쳐있기 때문에 언제 일이 완료될지는 모르겠다. 그리고 CONSOLED 가 잘 진행되어 커널에서 VT 관련 코드를 완전히 제거할 수 있는 날이 어서 빨리 오기를…