유민우
06/11/09
1.DirectX의 역사
엔비디아와 ATI의 차세대 그래픽 칩셋인 G80과 R600의 가장 특징 중 하나는 DirectX 10의 지원이다. 이것 이외에 통합 세이더 아키텍쳐나 물리 연산 지원, 엄청난 하드웨어 사양 등이 있지만, 두 개의 그래픽카드는 모두 DirectX 10 아키텍쳐를 기반으로 설계가 되었다.
DirectX는 그래픽 API(Application Programmable Interface) 중 하나로, 이 전에는 3dfx의 Voodoo에서 사용하는 Glide 모드와 또 다른 표준으로 OpenGL이 있었다. 이러한 API를 사용하기 전에는 모든 응용프로그램들이 자체적으로 그래픽카드에 대한 드라이버를 제공하였으며, 자신이 사용하는 그래픽카드의 드라이버가 없다면 어디에선가 문제는 발생하기 마련이었다. 이 때에는 윈도우라는 그래픽 유저 인터페이스를 지원하는 운영체제도 없었다. (굳이 언급을 한다면 IBM의 OS/2나 리눅스의 X-Window 정도라고 할까)
DirectX와 같은 API가 존재하기 전에, 모든 3D 응용프로그램은 그래픽 하드웨어와 직접적으로 드라이버를 통해 통신을 하게 되었다. 이런 직접적인 통신은 매우 빠른 속도를 제공한다는 장점이 있지만, 개발자들 입장에서는 모든 응용프로그램마다 시중에 출시되어 있는 그래픽카드 칩셋에 대한 드라이버를 만들어야 한다는 어려움과 함께 사용자 입장에서도 자신이 사용하는 그래픽카드의 드라이버가 제공되지 않는 응용프로그램은 사용할 수 없다는 불편함이 존재하였다.
그러던 때에 마이크로소프트는 기존에 Glide 모드와 경쟁을 할 수 있는 DirectX라는 API를 선보인다. 물론 이 때에는 윈도우 95라는 GUI 기반의 운영체제가 있기 때문에 가능한 것이었다. 윈도우95는 모든 드라이버를 운영체제 레벨 하에 관리를 하였기 때문에 응용프로그램들은 운영체제에서 자원만 불러다가 사용하면 되었기 때문에 어느 정도의 인프라는 갖춰졌기 때문이다.
개발자들은 더 이상 응용프로그램에 맞춰서 3D 응용프로그램을 개발하지 않고 DirectX의 아키텍쳐에 맞는 드라이버를 만들어내고 하드웨어 제조사의 칩셋 개발자 역시 DirectX라는 표준에 맞추기 시작하면서 3D 가속기의 발전은 시작되고 이 때에 엔비디아에서는 NV1이라는 3D 칩셋을 최초로 선보인다. 이 칩셋을 장착한 그래픽카드의 대표 제품은 엣지3D (Edge 3D)라는 당시 30만원이 넘는 고가의 가속기로써 버추어 파이터 1을 번들로 제공하던 그 제품이다.
<3DMark 2001의 Environment Bump Mapping 테스트 장면>
이후 DirectX는 버전업을 계속함에 따라 DirectX 6에서는 Environment Bump Mapping 이라는 기술이 사용된다. 이 기술은 2D 표면에 굴곡을 넣어 엠보싱처럼 표현해 주는것으로써 물체의 질감을 사실적으로 표현할 때 사용하는 기술이며 매트록스에서 처음으로 자사의 그래픽카드에 EMBM을 추가하였다.
그리고 DirectX 7이 되면서 T&L (Transform and Lighting)이 CPU에서 그래픽 코어로 넘어옴에 따라 그래픽 코어는 비로소 GPU라는 명칭을 얻을 수 있게 된다. 지오메트리 연산의 일부를 GPU에서 담당함으로써 CPU는 상당한 부담감을 해소할 수 있었고 일부 지오메트리 연산과 A.I. 그리고 물리 연산만을 담당하게 된다. 하드웨어 T&L은 엔비디아의 지포스 256에 처음으로 추가되었다.
[강좌] Transform and Lighting
DirectX 8. 드디어 세이더라는 개념이 생긴다. 세이더 모델 1.0에 대한 개념이 처음 생기고 프로그래머블 픽셀 세이더 1.0과 버텍스 세이더 1.0이 등장한다. 이때 한 가지 재미있는 사실은 DirectX 8.1에서 엔비디아는 픽셀 세이더 버전 1.3을, ATI는 픽셀 세이더 버전 1.4를 따로 선보였었다.
<3DMark2001 픽셀 세이더 테스트 장면>
그리고 현재의 DirectX 9는 가장 많은 버전 업이 되면서 세이더 모델 2.0부터 세이더 모델 3.0까지 모두 포함되어 있다. 세이더 모델의 버전이 올라감에 따라 한 번에 처리할 수 있는 명령어의 수도 늘어나게 되었고, 이는 픽셀 세이더 1.0에서 한 번에 12개의 명령어를 처리하던 수준에서 1.3은 28개, 2.0은 96개, 2.0b는 1536개, 3.0은 이런 제한이 사라지게 된다.
마지막으로 DirectX 10은 ATI에 의해 올해 4월 처음으로 선보였다. 그리고 이 API는 데스크탑이 아니라 콘솔 게임인 Xbox 360에 처음으로 적용되었다. 통합 세이더 아키텍쳐라는 특이한 파이프라인 구조로 되어 있는 이 API가 오늘 강좌의 주인공이다.
2.DirectX 9 무엇이 문제인가?
기존의 DirectX는 그 뼈대는 변하지 않고 여러가지 살만 붙으면서 성장을 하였다. 이는 처음 1.0이 만들어졌을 때 성능보다는 개발자들의 편의와 호환성을 위한 것이었고 성능을 따지기 시작한 것은 T&L을 GPU에서 처리하기 시작한 DirectX 7 때부터이다.
그러나 이런 DirectX의 고질적인 문제가 있으니 바로 CPU에 과부하를 너무 많이 준다는 것이다. DirectX 자체가 CPU 과부하의 주범이다.
위의 프리젠테이션 자료는 DirectX 10의 설계에 참여한 ATI가 제시한 것으로써, 이를 참조하자면 응용프로그램에서 DirectX 를 호출하고 DX에서는 드라이버를, 드라이버에서는 GPU에 오브젝트를 호출한다. 응용프로그램에서 DX로 오브젝트를 호출 할 때에는 상관이 없지만, DX에서 드라이버로 다시 호출할 때 오버헤드(overhead)가 추가로 붙는다. 문제는 이 오버헤드가 DX를 거칠 때마다 매번 붙는다는 것이다. 이러면 처리 시간이 길어지게 되어 정작 중요한 명령어 처리는 못하고 오버헤드 처리하는데 시간을 낭비하게 된다. 더 큰 문제는 바로 이 과정이 CPU에서 처리한다는 것이다.
이 오버헤드가 가져오는 문제점은 2가지이다. 한 번에 렌더링할 수 있는 오브젝트 수의 제한과 화면에 보여지는 이펙트의 제한이다. 이런 문제는 개발자들도 잘 알고 있었고 이를 해결하기 위한 방법도 존재한다.
DirectX 10의 탄생
DirectX 10의 가장 큰 변화점은 CPU의 간섭을 최소화하고 - CPU에서 담당하는 일을 GPU가 담당 - 기존 DX 8/9에서 나뉘어져 있던 픽셀과 버텍스 세이더 유닛을 하나로 통합했다는 것이다.
DirectX 10은 윈도우 비스타에 처음으로 사용되어지며 기존 운영체제는 지원을 하지 않는다. 마이크로소프트에서 밝힌 DirectX 9.L은 윈도우XP에서 DirectX 10 호환 그래픽카드를 사용할 수 있도록 해주는 것이 아니라 윈도우 비스타에서 DirectX 9 호한 그래픽카드를 사용할 수 있게 해주는 것이다. 이를 통해서 우리는 한가지 알 수 있다.
DirectX 10과 기존 DirectX 9는 호환이 안 된다는 점. 호환이 된다면 굳이 DirectX 9.L이라는 또다른 API를 만들어낼 필요가 없이 DirectX 9 호환 그래픽카드를 그냥 DirectX 10을 사용하면 되기 때문이다. 여기에서 호환이라 하면 통합 세이더 아키텍쳐의 사용이다. DX9에서는 통합 세이더 아키텍쳐를 위한 설계가 전혀 되어 있지 않기 때문이다.
3.CPU의 부담을 덜어라
DX10의 지상 과제 중 첫 번째인 CPU로부터의 독립 선언은 CPU의 의존도를 줄이는 것이다. CPU의 의존도를 줄이기 위한 방법 중 하나로 우선은 DX9에서 발생하는 오버헤드를 제거하는 것이다. 이를 위해서 DX10에서는 새로운 런타임 모델을 만들어냈다. DX9에서는 오브젝트를 호출할 때 마다 유효성(Validation)을 확인하는 작업을 하였다. 문제는 이 작업이 한 두 번에 그치는 것이 아니라 수백만 번씩 이루어진 다는 것인데, 이 유효성 작업을 오브젝트의 루프 전에 한 번만 하고 끝낸다는 것이다.
CPU에서 진행하는 이 작업이 수 백만에서 한 번으로 줄어든 다는 것은 그만큼 CPU의 부담이 줄어든다는 뜻이다. 이와 함께 CPU의 의존률을 줄이기 위해서 3가지 새로운 기능이 추가된다. 이것들은 각각 texture array Texture array는 최고 512개까지의 텍스쳐를 저장해 놓은 구조체로써, 여기에는 세이더 프로그램이 texture array 내부에서 동적으로 텍스쳐들을 색인할 수 있는 명령어들도 포함되어 있다. Texture array는 GPU에 의해 컨트롤이 되기 때문에 다량의 텍스쳐, 즉 멀티플 텍스쳐를 관리할 때 CPU의 의존도를 줄이게 된다. Predicated draw는 겹쳐지는 오브젝트를 처리할 때 사용하는 기능으로써, 앞쪽에 있는 오브젝트에 가려져 있는 뒤쪽의 오브젝트를 렌더링 하기는 하지만 최종적으로 보여지는 이미지에서는 효과를 제외하고 그려내는 것이다. 즉 불필요한 부분까지 세이더 처리를 하기 때문에 그만큼 자원 낭비가 이루어지는 것을 막아낼 수 있다. 이와같은 기법은 현재에도 사용되고 있지만 여전히 처리하지 말아야 할 부분까지 세이딩을 하게 된다. 이런 것을 occlusion query라 불렀으며 DX9 기반에서는 이를 CPU와 GPU가 담당했지만 DX10에서는 오직 GPU에서만 처리를 하게 된다. Stream out은 지오메트리 또는 버텍스 세이더의 결과물을 비디오 메모리로 바로 출력하는 새로운 기능이다. 기존에는 버텍스 -> 지오메트리 -> 픽셀 세이더 파이프 라인 순서를 반드시 거쳐야했지만 stream out을 통하면 픽셀 파이프 라인을 거치지 않고 바로 출력이 가능하게 되는 것이다. 이는 DX10의 통합 세이더 아키텍쳐가 있기에 가능한 것이다. 이런 기능 등을 이용했을 경우 줄어드는 오버헤드의 양은 다음 그래프를 참조하자 여기에서 세이더 파이프라인의 프로그래밍이란 기존의 프로그래머블 픽셀/버텍스 세이더를 말하는 것이 아니다. 세이더 유닛(스트림 프로세서)의 사용을 프로그래머가 버텍스나 픽셀 세이더로 임의 할당할 수 있다는 뜻이다. 기존에는 하나의 파이프라인에 픽셀/버텍스 세이더 유닛의 수가 고정되어 있었다. 우선은 세이더 모델 3.0과 세이더 모델 4.0의 차이점을 간단히 표로 정리해 보면, 리소스 DirectX 9 DirectX 10 와 같다. 한 번의 사이클에 처리할 수 있는 텍스쳐의 수가 DX9에서는 16개이지만 DX10에서는 128개로 늘어났으며, 멀티 렌더링 시 동시에 처리할 수 있는 픽셀 세이더의 수도 4개에서 8개로 늘어났다. 또한 텍스쳐의 크기 역시 기존 4096 x 4096에서 최대 4배가 커진 8192 x 8192까지 지원을 한다. 또한 세이더 모델 4.0에는 새로운 2개의 HDR 포맷이 추가 되었다. DirectX 9에서 사용하던 FP16이나 FP24 이외에 R11G11B10 모드와 R9G9B9+5 모드이다. R11G11B10은 레드와 그린이 각각 11bit씩을 사용하고 B는 10bit를 사용하여 FP32bit로 구성된다. FP16은 3가지 색상을 더해서 16bit가 아니라 하나의 색상에 16bit씩이다. R9G9B9+5의 경우에는 각 색상이 9bit씩을 사용하고 5bit는 공유를 한다. DX10의 새로운 모드 2개의 특징이라면 DX9의 FP16이 부동소수점 64bit (RGB 16bit씩 + 알파채널 16bit)에 비해 저장 공간은 절반이면서도 동일한 범위의 다이나믹 레인지를 표현할 수 있다는 것이다. 그러고 보다 높은 정밀도를 요구하는 HDR의 경우에는 색상 당 32bit에 알바 비트 32bit를 더해서 128bit의 정밀도로 구현을 할 수 있다. 이전 FP16일 경우에는 64bit로 구현이 되었었다. 이를 통해 실시간 Displacement Mapping, Stencil Shadow Extrusion, 점으로부터 Point-Sprite 생성, Motion Blur 그리고 이외에 많은 효과를 GPU에서 직접 처리할 수 있게 되었다. 지오메트리 세이더는 버텍스 세이더와 래스터라이저 사이에 위치해 있다. DX10의 파이프라인 구조는 DX9의 파이프라인과는 조금 다르다. DX9까지는 하나의 파이프라인에 버텍스 세이더와 픽셀 세이더가 존재했고 각각의 세이더에는 이를 처리하는 유닛이 있어서 이를 순차적으로 처리하였지만 DX10에서는 처리 순서가 버텍스 세이더->지오메트리 세이더->픽셀 세이더 순서로 처리가 이루어진다. 여기에서 한가지 특이한 것은 지오메트리 세이더와 래스터라이저 사이에 있는 Stream Output이라는 존재와 가상 비디오 메모리이다. Stream Output은 앞서 설명한 Stream Out 기능을 위해서 매우 중요한 역할을 한다. Stream Output을 통해 다시 Input Assembler로 보내어 지오메트리 데이터를 다시 구성할 수도 있고, 다른 세이더 유닛 그룹과 병렬처리도 가능해진다.
<DX10에서의 세이더 유닛> DX9의 세이더는 위의 그림에서 보이는 것처럼 세이더의 수가 고정되어 있다. 첫 번째 이미지에 대한 설명을 하자면, 상어를 표현할 때 픽셀 처리보다 버텍스 처리를 많이 하는 것으로 되어 있다. 이럴 때 고정된 세이더의 수는 버텍스 처리 시에 과부하가 걸리는 반면 픽셀 세이더는 활용할 수 있는 만큼 다 사용하지 못하고 아이들 상태로 대기를 한다. 마찬가지로 물을 표현할 때에는 버텍스보다 픽셀 처리를 많이 한다. 이때에는 반대로 픽셀 세이더는 과부하가 걸리는 반면 버텍스 세이더는 100% 활용을 하지 못하게 된다. 이런 낭비를 막으려면, 프로그래머가 DX9에서 제어 가능한 수의 픽셀/버텍스 세이더를 감안해서 최적화하여 프로그램을 만들면 되지만, 문제는 그래픽카드마다 버텍스와 픽셀 파이프라인의 수가 다르다는데 있다. 기준이 되는 그래픽카드가 없기 때문에 그래픽카드에 따라 성능 차이가 발생한다. 반대로 콘솔 게임의 경우에는 최신 그래픽카드보다 성능이 낮은 그래픽 코어를 사용함에도 불구하고 빠른 성능을 보여준다. 이는 하드웨어의 변경이 없이 하나의 기준에만 맞춰서 게임을 만들어내면 되기 때문이다. 그렇기 때문에 PC게임->콘솔 게임 또는 콘솔->PC 게임으로의 포팅이 잘 이루어지지 않는 것이다. 하지만 DX10의 경우에는 완벽하지는 않지만 PC와 콘솔 사이의 게임 포팅이 자유롭다. 물론 동일한 API를 사용하는 Xbox 360과 G80 또는 R600 그래픽카드를 사용한다는 전제하에서이다. CPU 부분에서 조금 걸리긴 하지만 그래도 그래픽 처리 부분에서는 상당한 자유도가 부여된다. DX10의 파이프라인 구조에서는 버텍스/픽셀/지오메트리 세이더의 수가 고정되어 있지 않고 하드웨어가 허용하는 범위 안에서 자유롭게 사용할 수 있다. 필자가 지난 4월에 발표된 DirectX 10을 지금에서야 재정리 해서 올리는 이유는, 이어지는 엔비디아의 지포스 8800GTX 때문이다. 코드명 G80을 GPU를 탑재한 엔비디아의 지포스 8800GTX는 DirectX 10의 아키텍쳐에 호환이 되는 데스크탑 최초의 그래픽카드이다. 또한 내년 1월에 선보이게 될 ATI의 R600에서도 동일하게 적용될 것이기에 앞서 정리를 한 것이다. 이론상으로는 획기적이기만 한 DirectX10을 지원하는 엔비디아의 지포스 8800GTX. 곧 공개가 되니 기대하기 바란다. [출처] [강좌] 통합 세이더 아키텍쳐로 진화한 DirectX 10|작성자 와우주 문제가 생길경우 삭제하겠습니다.
predicated draw
stream out
이라 불리운다.
4.세이더 모델 4.0 (Shader Model 4.0)
DX9에 포함된 세이더 모델 3.0과 DX10에 포함된 세이더 모델 4.0은 구조부터 다르다. DX10에 포함된 세이더 모델 4.0은 통합 세이딩 아키텍쳐(Unified Shading Architecture)라 불리우는 것이 사용되었으며 여기에는 픽셀 세이더, 버텍스 세이더 유닛과 함께 지오메트리 세이더라는 것이 추가되었다. 이로 인해서 세이더 파이프라인은 고정된 것이 아니라 개발자가 직접 프로그래밍할 수 있도록 되어 있다.
임시 레지스터 32 4096
고정 레지스터 256 65,536 (16 x 4096)
텍스쳐 16 128
렌더 타겟 4 8
최대 텍스쳐 크기 4096 x 4096 8192 x 8192
5.통합 세이딩 아키텍쳐 #1
세이더 모델 4.0에 새롭게 추가된 지오메트리 세이더는 단순히 CPU로부터 데이터를 넘겨받아 이를 처리하기만 하던 수동적인 입장에서 벗어나 직접 데이터를 생성하는 프로세서로써의 역할을 수행할 수 있도록 해주는 결정적인 계기를 제공한다. 기존 세이더 모델 3.0에서는 새로운 데이터를 생성하지는 못하고 오직 외부에서 넘겨 받은 메쉬(mesh)에 픽셀 단위로 세이딩 처리만 하였었다. 그러나 지오메트리 세이더를 탑재함으로써 트라이앵글을 직접 만들어 내는 작업까지 함으로써 CPU의 부담을 대폭 줄여주게 된 것이다.
6.통합 세이더 아키텍쳐 #2
7. DX10을 통한 또 다른 게임 세계를 만난다
DirectX 10은 DirectX 7 이후 성능에 중점을 두고 만들어진 또 다른 구조의 API이다. 버텍스 세이더와 픽셀 세이더를 GPU에서 처리하게 된 DX8에도 성능을 고려하지 않은 것은 아니지만 DX10의 지오메트리 세이더 추가와 통합 세이더 아키텍쳐는 지금까지와는 전혀 다른 구조를 갖고 있기 때문이다.
Xbox360에는 ATI의 통합 세이더 아키텍쳐가 사용된 1세대 GPU가 포함되어 있다. Xbox 360 사용자들은 잘 알고 있을 것이다. Xbox 360이 제공하는 이미지의 품질을. 그러면서도 전혀 느리다거나 하지는 않다는 것도 말이다. ATI는 데스크탑 최초의 DX10 GPU를 엔비디아에게 내주긴 했지만, Xbox 360 GPU 설계를 통해 얻은 노하우를 바탕으로 2세대 통합 세이더 아키텍쳐를 만들어 R600에 탑재할 것으로 보인다. 비록 엔비디아에 밀리긴 하지만 R600의 파워는 Xbox 360을 뛰어넘을 것으로 보인다.