강께르의 개발일지
[그래픽] 더블 버퍼링 본문
1. 버퍼란 무엇인가?
- 한 곳에서 다른 곳으로 데이터를 이동할 때, 임시적으로 그 데이터를 저장하기 위해 사용되는 물리적인 메모리 저장소의 영역이라고 한다.
- 이에 대한 설명으로는 출체에서 다음과 같이 얘기한다.
- 예를 들어 A와 B라는 소프트웨어 혹은 하드웨어가 있다고 하자.
- A는 어떤 작업에 대한 결과물로 특정 데이터를 내놓을 것이다. B는 특정 데이터를 입력받아서 작업을 한다고 가정하자.
- 여기서 '데이터를 내놓는다'의 의미는 특정 메모리 영역에 데이터를 기록한다는 의미이다. 특정 메모리 영역의 입장에서는 데이터를 저장한다고 해석이 될 것 같다.
- 그리고 '데이터를 입력 받는다'는 의미는 특정 메모리 영역의 데이터를 읽는다는 것을 의미한다. 특정 메모리 영역의 입장에서는 데이터를 넘겨준다고라고 해석 될 수 있을 것 같다.
- 이 상황에서 A의 결과로 나온 데이터를 B에 입력하는 게 목적이다.
- A에서 내놓은 데이터를 특정 메모리 영역 'a'에 저장하고 B에서 특정 메모리 영역 'a'의 데이터를 읽게 하는 일련의 과정을 수행하면 목적을 달성하게 될 것이다.
- 이 때, 여기서 특정 메모리 'a'는 버퍼라고 칭하는 것이다.
- 흔히 알고 있는 '버퍼링'은 버퍼를 특정 데이터로 채우는 동작을 이야기하는 것이다.
A(SW or HW) | 특정 메모리 영역 'a' 버퍼(Buffer) 데이터 이동 시, 임시 저장 메모리 |
B(SW or HW) |
특정 데이터를 내놓는다. | 특정 데이터를 입력 받는다. |
- 왜 데이터가 이동할 때 임시 저장할 필요가 있는 것일까?
- 버퍼에 데이터를 채우는 동작을 의미하는 버퍼링을 쓰는 대표적인 예는 인터넷 상에서의 동영상 시청이 있을 것이다.
- 인터넷에서 동영상을 시청 시, 그 모든 영상을 다 다운로드 받아서 재생하는 것이 아니다.
- 유튜브를 예로 동영상 시청 시, 현재 재생하고 있는 바가 있을텐데 그 바를 보면 빨간색 진행바는 현재 재생되고 있는 부분을 의미하고 동영상을 현재까지 다운로드 받은 부분을 회색으로 되어 있을 것이다.
- 이처럼 현재 데이터를 다운로드하여 바로 재생할 수 있다는 의미인데 이는 버퍼가 데이터를 받았기 때문에 가능한 것이다.
- 우리가 동영상을 재생하여 보는 속도와 인터넷을 통해 동영상을 다운로드 받는 속도가 차이가 나기 때문에 버퍼를 사용해서 다운로드를 받아 재생할 수 있는 것이다.
- 이 때, 동영상을 다운로드 받는 속도가 재생하는 속도보다 현저히 느리다면 버퍼에 다운로드받은 데이터가 없기에 동영상을 다운로드 받아 버퍼를 채우기까지 기다려야할 것이다.
- 이런 상황을 사람들이 흔히 쓰는 말로 '버퍼링 걸렸다'라고 하는 것이다.
- 정리하자면 버퍼는 속도 차이가 있는 장치 사이에서 데이터를 전송할 때, 데이터 손실을 방지하고 데이터를 효율적을 사용하기 위한 임시 저장 공간이라 할 수 있다.
- 버퍼가 쓰이는 대표적인 예는 주변 장치와 CPU 간의 처리 속도 차이를 극복하기 위해 대기 시간을 줄이는 기법인 '스풀링'이나 하드 디스크 버퍼, 입출력 버퍼 등이 있다.
- 입출력 버퍼 중 키보드/모니터 버퍼의 예시가 있다. 키보드에서 입력하면 입력에 따라 데이터를 키보드 버퍼에 저장한다. 그리고 그 데이터를 쓰는 프로세스에서 읽어서 사용하는 것이다.
- 모니터의 버퍼는 그래픽 카드가 처리한 프레임 데이터를 저장하고, 그것을 순차적으로 프레임 단위로 화면에 출력할 것이다.
2. 프레임 버퍼
- 이 글에서 얘기할 더블 버퍼링은 화면에 출력할 때 생기는 문제를 해결하기 위한 방법이다. 그 전에 화면과 관련한 버퍼에 대한 이야기를 정리해야할 것 같다.
- 위에 대략적으로 얘기한 모니터의 버퍼가 바로 이 얘기일 것이다. 모니터에 출력하기까지 데이터의 흐름을 보면 다음과 같다.
GPU | Frame Buffer | Video Controller | Screen |
그래픽 연산 후 결과값을 버퍼에 출력 |
GPU의 데이터를 저장한 후, Video Controller에 입력 |
프레임 버퍼에서 데이터를 읽어서 화면을 Screen에 출력 |
- 위에서 이야기했던 모니터의 버퍼는 그래픽 처리에 관한 버퍼가 될 것인데 이 때 쓰이는 버퍼 이름을 프레임 버퍼라고 한다.
- 이 프레임 버퍼는 여러 가지 그래픽에 관한 정보를 가지고 있다. 적자면 다음과 같다.
- 화면에 그려질 화면 전체에 대한 정보라고 하는데 그 중 색깔 정보, 2D 좌표계 정보, 어느 위치에 그림을 그릴지에 대한 정보가 있다. color, depth, stencil이라고 출처에서 이야기하지만 대략적으로 이해만 하자.
- 이 버퍼를 사용하는 중에 생기는 문제를 해결하기 위해 쓰이는 것이 더블 버퍼링이다.
3. 프레임 버퍼를 사용하며 겪는 문제
- 프레임 버퍼를 통해 데이터가 거치면서 모니터에 그래픽 연산한 결과를 보여줄 것이다.
- winapi를 통해 그래픽 연산 데이터를 화면에 보면서 겪는 불편함이 있다. 그것은 화면에 보이는 결과물이 움직인다는 등 변경되는 일이 있을 때마다 깜박거린다는 것이다.
- 무시한다고 한다고 하면 계속 무시할 수야 있겠지만, 프로그래밍을 통해 게임을 만든다고 가정했을 때, 게임이 화면에 보여주는 결과물이 계속 깜박거리는 현상이 있다고 한다면 그것은 사용자로 하여금 불만족스러운 경험을 안겨줄 것이다.
- 이를 해결하기 위해서는 이 현상의 이유를 알아야할 것 같다.
- 앞서 버퍼에 대한 이야기를 할 때, '버퍼링 걸렸다'의 이유는 영상을 재생하는 속도에 비해 영상을 다운로드하는 속도가 느리기 때문이라고 했다.
- 프레임 버퍼도 이와 비슷한 현상을 겪는 것이다. 일반적으로 GPU가 프레임 버퍼에 데이터를 출력하는 작업은 Video Controller가 프레임 버퍼를 입력받는 속도에 비해 훨씬 느리다.
- GPU로부터 데이터를 온전하게 출력받지 못한 채 데이터를 저장하고 있는 중인 상황의 프레임 버퍼에서 Video Controller에게 온전한 데이터를 입력할 수 없다. 불완전한 데이터가 입력될 것이다.
- 그렇기에 화면에 결과물을 보여주고 다음 화면에 GPU로부터 넘어온 데이터를 결과물로 보여줘야하는데 아직 넘어오는 중이거나 넘어오지 않았기에 지우고 계산하여 그려서 출력하는 패턴을 반복하다보니 사용자의 눈에는 화면이 깜박거린다는 인식을 하게 되는 것이다.
4. 더블 버퍼링
- 이 문제를 해결하기 위해 드디어 더블 버퍼링 이야기를 정리할 수 있게 되었다.
- 일단 더블 버퍼링을 구성을 표현한 그림을 보고 다시 정리하겠다.
GPU | Front Frame Buffer | Video Controller | Screen |
Back Frame Buffer |
- 더블 버퍼링은 GPU가 내놓는 데이터를 저장하는 작업인 버퍼링을 두 버퍼로 사용하는 방법을 말한다.
- Video Controller가 Front Frame Bufffer의 데이터를 입력받아서 Screen으로 사용자에게 보여주는 동안, Back Frame Buffer는 GPU로부터 다음 그려질 내용에 대한 데이터를 받아 저장할 것이다.
- GPU가 Back Frame Buffer에 데이터를 전부 넘겼다면 Video Controller는 Back Frame Buffer의 데이터를 입력받아 Screen으로 사용자에게 보여줄 것이다.
- 그와 동시에 GPU는 Front Frame Buffer에게 다음 화면에 대한 새로운 그래픽 데이터를 출력할 것이다.
- Video Controller와 GPU는 두 개의 버퍼를 번갈아가며 사용하면서 데이터를 저장하고 가져와서 쓰는, 데이터를 출력하고 입력하는 과정을 계속 바꿔가면서 진행할 것이다.
- 그래서 Video Controller는 그림이 그려진 종이를 사용자에게 보여주는 동안 GPU가 다음 보여줄 화면을 다른 종이를 계속 그리다가 완성되면 그 종이를 Video Controller의 종이와 바꿔 넘겨주고, 다시 그리는 것이다.
- Video Controller 입장에서는 계속 해서 완전한 데이터로 화면에 출력할 수 있게 하는 것이다.
출처 :
'프로그래밍 > 미분류' 카테고리의 다른 글
[에러] _CrtisValidHeapPointer(block)에 대해 (0) | 2021.07.05 |
---|