5. Direct3D 기본개념 다지기 - 스왑체인
SwapChain
그래픽 어댑터는 모니터에 디스플레이되고 있는 이미지를 표현하는 Surface에 대한 포인터를 가지고있다.
이것을 전면 버퍼(front buffer)라 부른다.
모니터가 갱신되면 그래픽 카드는 전면 버퍼의 내용들을 디스플레이를 위해 모니터로 보낸다.
하지만 실시간 그래픽 렌더링에서는 여러 가지 난해한 문제가 생긴다.
모니터 주사율은 일반적으로 60Hz에서 100hz인데 컴퓨터에 비해 느린 주사율 덕택에
만약 게임을 한다고 치자. 컴퓨터가 너무 좋아서 게임이 120fps를 찍어버렸다.
화면 주사율은 60hz = 1초에 6번 분사되는데 120프레임은 초당 120개의 프레임이 지나간다. (물론 120fp까지 올라가지 않도록 대부분 막아놓거나 제한을 건다.)
그렇게 될 경우 주사율보다 빠른 성능때문에 전면버퍼를 갱신하고 있으면 화면 위쪽은 전 이미지가 나오고 아래쪽 화면은 새롭게 갱신되는 이미지 때문에 결국 tearing (잘림) 현상이 일어난다.
그래서 전면버퍼 혼자 힘겨우니까 미리 뒤에서 준비해줄 애를 만들어줬다.
백버퍼 또는 후면 버퍼라고 부른다.
API에서는 더블 버퍼링 기법(전면버퍼, 후면버퍼)을 이용한 화면분사 방식을 대게 사용했다.
Direct3D는 두 가지의 보완 방식을 사용하는데 그 중 하나가 스왑체인이다.
보통 두 개나 세 개의 표면을 하나의 컬렉션으로 관리하며, 이를 스왑체인이라 부른다.
스왑체인은 IDirect3DSwapChain9 인터페이스를 통해 이용할 수 있지만, 대부분의 작업은 Direct3D가 직접 관리하므로 우리가 이 인터페이스를 이용하는 경우는 거의 없다.
표면1: 전면버퍼 : 이 버퍼의 내용물은 현재 모니터에서 보여지고 있는 것
표면2: 후면버퍼 : 현재 처리중인 프레임이 이 버퍼에 보관된다.
또 다른 하나는 다이렉트는 이 문제를 해결하기 위해 수직회귀 연산에 맞춰 모니터를 갱신하도록 한다. 게임 옵션에서 보면 수직동기화가 있는데 이와 같은 옵션이다. 관련되서 수직동기화에 관한 글을 찾아보는 것도 좋다.
API의 더블 버퍼링과 Direct3D의 스왑체인은 똑같은 역할과 기능을 가지고 있지만 약간 다른 방식이다.
더블버퍼링은 서로의 역할을 분담해서 버퍼를 고정적으로 보관버퍼(후면), 분사버퍼(전면)로 나뉜다. 후면 버퍼에서 다음 렌더링을 미리 준비하고 전면으로 보내주면 전면은 화면에 분사한다. 두 프레임 버퍼의 역할은 고정이고 계속 반복한다.
스왑체인은 보관버퍼와 분사버퍼가 서로 교대하면서 분사하고 보관한다. 2번 버퍼가 준비하면 1번 버퍼 렌더링을 하고 끝남과 1번은 준비하고 2번이 분사하고 무한 반복..
우리가 내리는 모든 명령들은 대부분 보이지 않는 후면 버퍼에 그려지고, 특정한 명령에 의하여 후면 버퍼를 보이는 화면인 전면 버퍼로 전송하게 된다.
이렇게 하지 않을 경우 전면 버퍼에서 화면을 지우고 다시 그려야 하는데, 이 경우 깜빡임 현상이 발생하게 된다.
이를 막는 가장 효율적인 방식은 페이지 플리핑 방식이며, D3D에서 후면 버퍼의 내용을 전면 버퍼로 전송하는 명령은 Present()다