DirectX를 공부하려는데 뭘 하면 좋을지 뭔가를 만들어야 할지 아니면 이론을 쌓을지 고민했다! 재밌긴 하지만 지금 당장 우선순위는 이론과 적절한 실습이 맞다 생각하여 서칭하다 좋은 자료를 발견하여 공유합니다.
참고 사이트 및 출처: DirectX 11 기초 (Tutorial)-.. : 네이버블로그 (naver.com)
※ 저는 추후에도 제 글을 통해 공부할 것이기에 필기한다는 생각으로 다시 한번 정리했습니다.
컴퓨트 셰이더
OS나 일반 어플리케이션 등을 실행하는 범용 프로세서인 CPU와는 달리 그래픽스 처리에 특화된 전용 프로세서를 GPU라고 하는데 DirectX 11에는 Compute Shader를 지원함으로써 그래픽스 처리 이외에도 데이터를 병렬처리할 수 있는 범용적인 프로세서로써 GPU를 활용할 수 있다.
컴퓨트 셰이더는 DirectX 디바이스를 통해 그래픽스 계열 셰이더와 리소스를 공유하지만 다른 셰이더와는 직접 연결되지 않는다.
테셀레이션
Tessellation은 정밀도가 낮은 primitive (DirectX에서 렌더링 하는 도형의 최소 단위 점, 선, 삼각형) 데이터들을 분할하여 보다 정밀하게 primitive를 생성하여 출력하는 기능
DirectX 11의 그래픽스 파이프라인에는 테셀레이션을 수행하는 1개의 스테이지와 2개의 셰이더(Hull Shader, Domain Shader)가 추가되어 리얼타임으로 테셀레이션을 수행할 수 있다.
멀티 스레드 렌더링
DirectX 11에선 멀티 스레드 호환이 강화되어 DirectX 10의 디바이스 기능은 디바이스와 디바이스 컨텍스트로 분할됐다.
- 디바이스 컨텍스트에는 Immediate Context와 Deferred Context가 있다.
- Immediate Context는 디바이스에 직접 렌더링하는 디바이스 컨텍스트로 디바이스에 1개만 존재. 싱글 스레드의 어플리케이션은 이미디에이트 컨텍스트만을 사용한다.
- Deferred Context는 메인 렌더링 스레드 이외에 워커 스레드에서 사용하는 디바이스 컨ㄴ텍스트이다.
- 디바이스의 메소드는 프리 스레드화 돼있는데 다비이스 컨텍스트의 메소드는 프리 스레드화 되어 있지 않다.
동적 셰이더 링크
일반적인 렌더링에서는 각종 머티리얼을 여러가지 조합을 통하여 렌더링을 수행하고 있다. 이로 인해 렌더링마다 기능이 다른 셰이더가 필요하다. 그렇기에 이전에는 모든 기능을 갖춘 셰이더를 만드는 방법과 필요한 조합의 셰이더만을 사용하는 방법 등을 사용했다.
모든 기능을 갖춘 셰이더를 만드는 방법은 셰이더의 퍼포먼스가 떨어지며, 필요한 조합의 셰이더만을 사용하는 방법은 조합이 조금만 증가해도 방대한 양의 셰이더를 관리해야 한다.
DirectX 11에서 도입된 동적 셰이더 링크는 파이프라인에 할당할때에 셰이더 코드를 드라이버에 최적화 할 수 있도록 되어있다.
WARP (Windows Advanced Rasterizer Platform)
실제 어플리케이션에서 사용 가능한 고속의 멀티코어 스케일링 래스터라이저다. Direct3D 10.1 레벨의 기능을 지원하고 있으며 어플리케이션에서는 필요한 하드웨어 디바이스를 얻을 수 없는 경우 WARP 디바이스를 선택할 수 있다.
비슷한 기능으로 DirectX의 모든 기능을 소프트웨어로 정확히 구현한 레퍼런스 래스터라이저가 있으나 이는 실행 속도가 매우 느리고 개발용으로만 사용 가능하다.
실행 속도 순서는 하드웨어 > WARP > 래퍼런스 래스터라이저
Direct3D 9/10/10.1 레벨의 하드웨어 지원
DirectX 10을 사용한 어플리케이션을 실행하려면 DirectX 10을지원하는 그래픽스 하드웨어는 필수다. 그러나 DirectX 11에서는 6단계의 Feature Level을 정의하여 DirectX 9/10/10.1 디바이스여도 호환할 수 있는 Feature Level에 따른 DirectX 11의 기능을 사용한 어플리케이션을 실행 할 수 있다.
Direct 3D 10의 특징들 계승
DirectX 10을 확장한 설계로 DirectX 10에 특징인 디바이스 로스트 처리가 불필요하며 CAPS 비트의 폐지 고정기능 파이프라인 폐지 지오메트리 셰이더 같은 특징들을 계승하고 있다.
Shader Model 5.0
DirectX 10/11 에선 통합형 셰이더 Unified-Shader 아키텍처가 채택됐으며 컴퓨트 셰이더를 포함한 모든 셰이더를 하나의 HLSL로 작성할 수 있다.
리소스
DirectX 11 에서는 읽기/쓰기 버퍼(텍스처), 구조화된 버퍼, 바이트 어드레스 버퍼, Unordered Access 버서(텍스처) 등의 새로운 리소스 타입이 정의 되어 있다. 또한 4GB 보다 큰 리소스를 지원하는데 리소스 인덱스는 32-bit
Direct3D 11과 DirectXGI
Direct 3D 11은 그래픽스에 관한 기초적인 기능을 제공하는 DirectXGI 상에 구축되어 있다. DirectXGI는 DirectX 11등의 그래픽스 기능이나 어플리케이션으로부터 오는 표시를 받아 커널 모드 드라이버나 하드웨어와 주고 받는 역할을 한다.
일반적으로 Direct3D 11을 사용할 경우 DirectXGI의 관해선 Direct3D 11 경유로 다루기 때문에 어플리케이션 측에서 직접 조작하는 것은 거의 없으나 감마 컬렉션이나 출력에 관한 디스플레이를 선택하는 등의 컨트롤이 필요한 경우에 DirectXGI를 사용하게 된다.
Swap Chain
DirectXGI의 중요한 기능으로 DirectX 11에서는 화면의 표시와 렌더링에 Front Buffer와 Back Buffer를 사용한다.
Front Buffer는 디스플레이상 표시되고 있는 화면 데이터를 가지고 있는 버퍼이다. 일단 Back Buffer에 쓰고, 렌더링이 끝났을 때 디스플레이에 표시되는 버퍼의 내용을 한번 갱신(Update) 한다. 또 갱신 작업 중에는 Back Buffer에도 렌더링은 할 수 없다. 따라서 렌더링 퍼포먼스의 저하를 막기 위해 3개 이상의 버퍼를 준비하는 것도 가능하다.
Front Buffer나 Back Buffer를 포함한 여러 버퍼의 집합과 전환 방식을 Swap Chain이라 한다.
DirectX 11의 Pipe-Line (마이크로 소프트 공식 문서도 같이보면 좋다)
렌더링 파이프라인 안을 흐르는 데이터에는 '파이프라인에 의해 선택되는 값 (시스템 값)' 과 '파이프라인과 관계 없는 값' 이 있다. 예를 들어 SV_POSITION 이라는 시맨틱스(속성)를 가진 데이터는 파이프라인에 의해 Vertex 좌표로 다루게 되며 래스터라이저는 이 값을 바탕으로 래스터라이저 처리를 수행한다. 반면에 유저가 정의한 시맨틱스를 가진 데이터는 유저에 의해 작성된 셰이더 코드 내에서만 사용된다. 즉 유저는 셰이더가 필요로 하는 임의의 데이터를 파이프라인에 넣을 수 있다는소리다.
파이프 라인 안을 흐르는 데이터에는 '유저에 의해 선택된 값' 과 '입력 어셈플러등에 의해 생성된 값(시스템 생성값)' 이 있다. 버텍스 좌표등의 유저에 의해 제공된 값은 버텍스 버퍼로부터 Input Assembler를 통해서 파이프라인에게 넘겨 주거나 셰이더 코드로 생성하거나 한다. 이에 반해 버텍스 ID, 프리미트 ID, 인스턴스 ID 등의 시스템 생성 값은 Input Assembler에 의해 생성되어 파이프라인에 제공된다.
파이프라인에서 설명하는 단어 의미
-Vertex Buffer와 Index Buffer: 각 프리미티브 정보는 버텍스 버퍼와 인덱스 버퍼에 저장하여 파이프라인에 넘긴다. 버텍스 버퍼에는 프리미티브의 각 버텍스의 좌표나 머티리얼 정보(색 등)을 저장한다. 버텍스 버퍼는 동시에 최대 16(또는 32)개까지 사용할 수 있다.
-Input Assembelr: 파이프라인에서 첫 스테이지다. 리소스로부터 데이터를 읽어 들여 파이프라인에 데이터를 제공하는 일을 한다. 동시에 프리미티브 ID, 인스턴스 ID, 버텍스 ID 등의 '시스템 생성값'을 생성하여 파이프라인에 제공한다.
-Vertex Shader: 셰이더 입력으로 버텍스 데이터를 1개 취해 좌표 변환등을 수행한 후 버텍스 데이터 1개를 출력한다.
-Hull Shader: DirectX 11에서 새로 추가된 테셀레이터 기능을 구성하는 셰이더의 하나다. 셰이더 입력으로 1~32개의 '컨트롤 포인트'를 취해 1~32개의 '컨트롤 포인트', '배치 정수', '테셀레이션 개수'를 출력한다. 출력 데이터는 테셀레이터 스테이지와 도메인 셰이더에 넘겨진다
-Tessellator: DirectX 11에서 새로 추가된 테셀레이터 기능을 구성하는 스테이지
-Domain Shader: 입력으로써 'Hull Shader'와 Tessellator에 출력을 취해 셰이더 출력으로써 배치 내의 각 버텍스 좌표를 출력한다.
-Geometry Shader: 셰이더 입력으로써 프리미티브 데이터 1개를 취해 프리미티브 변형이나 새로운 프리미티브의 생성을 수행한 후 셰이더 출력으로써 0개 또는 1개 이상의 프리미티브 데이터를 출력한다. 피리미티브를 줄이거나 늘릴거나 할 수 있다.
-Stream Output: GS(Geometry Shader)나 VS(Vertex Shader)로부터 출력을 리소스 내의 버퍼에 쓰는 스테이지다. 버퍼에 쓰여진 데이터는 CPU에서 읽어들여 사용하거나 파이프라인에 입력으로써 사용할 수 있다.
-Rasterize: 보이지 않는 프리미티브를 없애거나(컬링), 버텍스 값을 프리미티브 전체로 보완하여 프리미티를 Pixel 데이터로 분해한다. 래스터라이저 스테이지에 입력되는 데이터의 좌표 (x,y,z,w)는 모두 같은 Ciip 공간내의 좌표라고 간주된다.
-Pixel Shader: 셰이더 입력으로써 픽셀 데이터 1개를 취해 텍스처 처리나 라이팅등을 수행한 후 셰이더 출력으로써 픽셀 데이터 1개를 출력한다.
-Output Merger: 픽셀 셰이더로부터 출력된 픽셀 데이터나 Depth/Stencil 버퍼의 값을 사용하여 최종적으로 렌더링될 색을 결정한다. 이때 Depth/Stencil 테스트를 수행하여 실제로 렌더링할지 안할지를 결정한다.
-Texture와 Sampler: 리소스에는 텍스처 리소스와 버퍼 리소스가 있다.
버퍼 리소스는 1차원 배열로 구조화되어 있지 않으며 필터 처리의 대상도 되지 않으며 서브 리소스를 가질 수 있다. 멀티 샘플되는 것도 되지 않으며 본질적으로는 단순한 커다란 메모리라고 할 수 있다. 버텍스 버퍼와 인덱스 버퍼가 대표적인 버퍼 리소스다.
텍스처 리소스는 화상 데이터인 텍스처를보존하기 위한 구조화된 컬렉션이다. 텍스처는 셰이더에서 읽어들일때 샘플러에 의해 필터 처리할 수 있다. 1개 이상의 MipMap 레벨을 가질 수 있다.
-Constant Buffer: DirectX 11에서는 셰이더로 사용하는 정수값을 설정하는데 '정수 버퍼'를 사용한다. 개념적으로 버텍스 버퍼와 완전 똑같다. 각 스테이지에는 D3D11_COMMON_SHADER_CONSTANT_BUFFER_API_SLOT_COUNT(14)의 정수 버퍼를 할당할 수 있으며 각 정수 버퍼에는 최대 4096개의 정수를 설정할 수 있다.
-Render Texture: DirectX 11에서는 최대 8개 까지의 렌더 타겟을 설정할 수 있다. GS를 사용하여 프리미티브를 렌더링하는 렌더 타겟을 설정할 수 있다. 이 기능을 통해 큐브 텍스처의 6개의 면을 1 Path로 렌더링 할 수 있다.
-Depth / Stencil Buffer: Depth Buffer와 Stencil Buffer는 Depth/Stencil Buffer라는 1개의 리소스로써 묶어서 취급 된다. 사용은 옵션이며 2D 그래픽스 렌더링 같은데에서는 이를 사용하지 않을 수 도 있다.
분명 전공 그래픽스, GPU 프로그래밍 등에서 배워서 용어가 어색하거나 개념적으로 모르는건 없었다. 그러나 한번 더 개념을 다듬고 이 전체를 보며 구조를 그려나갈 수 있었다. OpenGL이든 DirectX든 차이는 있지만 전체적인 그래픽스 파이프라인이라는 것은 공통되므로 게임 개발자라면 꼭 알아두자!! 적어도 개념과 문제 상황에 따른 처리 능력을 위해서라도...
난... 아직도 갈 길이 멀구나
'DirectX 11 공부' 카테고리의 다른 글
01) DirectX 프레임 워크 (0) | 2023.11.06 |
---|