Direct3D 12는 Direct3D 11 프로그래밍 모델에서 크게 벗어난 것입니다. Direct3D 12를 사용하면 앱이 그 어느 때보다 하드웨어에 더 가까이 다가갈 수 있습니다. 하드웨어에 더 가까워지면 Direct3D 12가 더 빠르고 효율적입니다. 그러나 Direct3D 12로 속도와 효율성이 향상되는 앱의 장단 점은 Direct3D 11보다 더 많은 작업을 담당한다는 것입니다.
- 명시적 동기화
- 실제 메모리 상주 관리
- 파이프라인 상태 개체
- 명령 목록 및 번들
- 설명자 힙 및 테이블
- Direct3D 11 포팅
- 관련 항목
Direct3D 12는 하위 수준 프로그래밍으로의 복귀입니다. 파이프라인의 전체 상태를 나타내는 개체, 작업 제출을 위한 명령 목록 및 번들, 리소스 액세스를 위한 설명자 힙 및 테이블과 같은 새로운 기능을 도입하여 게임 및 앱의 그래픽 요소를 보다 잘 제어할 수 있습니다.
Direct3D 12로 앱의 속도와 효율성이 향상되었지만 Direct3D 11보다 많은 작업을 담당합니다.
명시적 동기화
- Direct3D 12에서 CPU-GPU 동기화는 이제 앱의 명시적 책임이며 Direct3D 11에서와 같이 런타임에서 더 이상 암시적으로 수행되지 않습니다. 또한 이 사실은 Direct3D 12에서 파이프라인 위험에 대한 자동 검사를 수행하지 않음을 의미하므로 다시 앱의 책임입니다.
- Direct3D 12에서 앱은 데이터 업데이트 파이프라인을 담당합니다. 즉, Direct3D 11의 "Map/Lock-DISCARD" 패턴은 Direct3D 12에서 수동으로 수행해야 합니다. Direct3D 11에서 ID3D11DeviceContext::MapD3D11_MAP_WRITE_DISCARD호출할 때 GPU가 버퍼를 계속 사용하는 경우 런타임은 이전 버퍼 데이터 대신 새 메모리 영역에 대한 포인터를 반환합니다. 이렇게 하면 앱이 새 버퍼에 데이터를 배치하는 동안 GPU에서 이전 데이터를 계속 사용할 수 있습니다. 앱에는 추가 메모리 관리가 필요하지 않습니다. GPU가 완료되면 이전 버퍼가 자동으로 재사용되거나 제거됩니다.
- Direct3D 12에서는 모든 동적 업데이트(상수 버퍼, 동적 꼭짓점 버퍼, 동적 텍스처 등 포함)가 앱에서 명시적으로 제어됩니다. 이러한 동적 업데이트에는 필요한 GPU 펜스 또는 버퍼링이 포함됩니다. 앱은 더 이상 필요하지 않을 때까지 메모리를 사용할 수 있도록 유지해야 합니다.
- Direct3D 12는 인터페이스 수명 동안만 COM 스타일 참조 계산을 사용합니다(디바이스 수명에 연결된 Direct3D의 약한 참조 모델을 사용). 모든 리소스 및 설명 메모리 수명은 적절한 기간 동안 유지 관리하는 앱의 유일한 책임이며 참조 횟수는 계산되지 않습니다. Direct3D 11은 참조 계산을 사용하여 인터페이스 종속성의 수명도 관리합니다.
실제 메모리 상주 관리
Direct3D 12 애플리케이션은 여러 큐, 여러 어댑터 및 CPU 스레드 간의 경합 상태를 방지해야 합니다. D3D12는 더 이상 CPU 및 GPU를 동기화하지 않으며 리소스 이름 바꾸기 또는 다중 버퍼링을 위한 편리한 메커니즘을 지원하지 않습니다. 펜스는 다른 처리 장치가 사용을 완료하기 전에 메모리를 과도하게 쓰는 여러 처리 단위를 방지하기 위해 사용해야 합니다.
Direct3D 12 애플리케이션은 GPU가 데이터를 읽는 동안 데이터가 메모리에 상주하는지 확인해야 합니다. 각 개체에서 사용하는 메모리는 개체를 만드는 동안 상주합니다. 이러한 메서드를 호출하는 애플리케이션은 GPU가 제거된 개체에 액세스하지 않도록 펜스를 사용해야 합니다.
리소스 장벽은 매우 세분화된 수준에서 리소스 및 하위 리소스 전환을 동기화하는 데 사용되는 또 다른 유형의 동기화입니다.
파이프라인 상태 개체
Direct3D 11을 사용하면 대규모 독립 개체 집합을 통해 파이프라인 상태를 조작할 수 있습니다. 예를 들어 입력 어셈블러 상태, 픽셀 셰이더 상태, 래스터라이저 상태 및 출력 병합기 상태는 모두 독립적으로 수정할 수 있습니다. 이 디자인은 그래픽 파이프라인의 편리하고 비교적 높은 수준의 표현을 제공하지만, 주로 다양한 상태가 상호 의존적이기 때문에 최신 하드웨어의 기능을 활용하지 않습니다. 예를 들어 많은 GPU는 픽셀 셰이더와 출력 병합기 상태를 단일 하드웨어 표현으로 결합합니다. 그러나 Direct3D 11 API를 사용하면 이러한 파이프라인 단계를 별도로 설정할 수 있으므로 표시 드라이버는 상태가 완료될 때까지 파이프라인 상태의 문제를 해결할 수 없으며 그리기 시간까지는 해결할 수 없습니다. 이 체계는 하드웨어 상태 설정을 지연하므로 프레임당 추가 오버헤드 및 최대 그리기 호출 수가 줄어듭니다.
Direct3D 12는 파이프라인 상태의 대부분을 PSO(변경할 수 없는 파이프라인 상태 개체)로 통합하여 이 체계를 해결합니다. 이 개체는 생성 시 완료됩니다. 그런 다음 하드웨어 및 드라이버는 GPU 작업을 실행하는 데 필요한 하드웨어 네이티브 지침 및 상태로 PSO를 즉시 변환할 수 있습니다. 사용 중인 PSO를 동적으로 변경할 수 있지만 이렇게 하려면 하드웨어에서 미리 계산된 최소한의 상태만 하드웨어 레지스터에 직접 복사하면 됩니다. 즉석에서 하드웨어 상태를 계산하는 것이 아니라. PSO를 사용하면 그리기 호출 오버헤드가 크게 줄어들고 프레임당 더 많은 그리기 호출이 발생할 수 있습니다. PSO에 대한 자세한 내용은 Direct3D 12 그래픽 파이프라인 상태 관리참조하세요.
명령 목록 및 번들
Direct3D 11에서 모든 작업 제출은 GPU로 이동하는 명령의 단일 스트림을 나타내는 직접 컨텍스트통해 수행됩니다. 멀티스레드 크기 조정을 달성하기 위해 게임에서는 지연된 컨텍스트도 사용할 수 있습니다. Direct3D 11의 지연된 컨텍스트는 하드웨어에 완벽하게 매핑되지 않으므로 비교적 적은 작업을 수행할 수 있습니다.
Direct3D 12는 GPU에서 특정 워크로드를 실행하는 데 필요한 전체 정보를 포함하는 명령 목록을 기반으로 작업 제출을 위한 새 모델을 도입했습니다. 각 새 명령 목록에는 사용할 PSO, 필요한 질감 및 버퍼 리소스, 모든 그리기 호출에 대한 인수와 같은 정보가 포함됩니다. 각 명령 목록은 자체 포함되고 상태를 상속하지 않으므로 드라이버는 필요한 모든 GPU 명령을 미리 미리 계산하고 자유 스레드 방식으로 계산할 수 있습니다. 필요한 유일한 직렬 프로세스는 명령 큐를 통해 GPU에 명령 목록을 최종 제출하는 것입니다.
명령 목록 외에도 Direct3D 12에는 번들두 번째 수준의 사전 계산 작업이 도입되었습니다. 완전히 자체 포함되고 일반적으로 생성되고 한 번 제출되고 삭제되는 명령 목록과 달리 번들은 재사용을 허용하는 상태 상속 형식을 제공합니다. 예를 들어 게임에서 서로 다른 텍스처를 사용하여 두 문자 모델을 그리려는 경우 한 가지 방법은 동일한 그리기 호출의 두 집합으로 명령 목록을 기록하는 것입니다. 그러나 또 다른 방법은 단일 문자 모델을 그리는 번들 하나를 "기록"한 다음 다른 리소스를 사용하여 명령 목록에서 번들을 두 번 "재생"하는 것입니다. 후자의 경우 디스플레이 드라이버는 적절한 지침을 한 번만 계산해야 하며 명령 목록을 만드는 것은 기본적으로 두 개의 저비용 함수 호출에 해당합니다.
명령 목록 및 번들에 대한 자세한 내용은 Direct3D 12 작업 제출을 참조하세요.
설명자 힙 및 테이블
Direct3D 11의 리소스 바인딩은 매우 추상화되고 편리하지만 많은 최신 하드웨어 기능이 사용되지 않습니다. Direct3D 11에서 게임은 리소스의 개체를 보기를 만든 다음 파이프라인의 다양한 셰이더 단계에서 여러 슬롯에 바인딩합니다. 셰이더는 그리기 시 고정되는 명시적 바인딩 슬롯에서 데이터를 읽습니다. 이 모델은 게임이 다른 리소스를 사용하여 그릴 때마다 다른 보기를 다른 슬롯에 다시 바인딩하고 그리기를 다시 호출해야 한다는 것을 의미합니다. 또한 이 사례는 최신 하드웨어 기능을 완전히 활용하여 제거할 수 있는 오버헤드를 나타냅니다.
Direct3D 12는 바인딩 모델을 최신 하드웨어와 일치하도록 변경하고 성능을 크게 향상시킵니다. Direct3D 12는 독립 실행형 리소스 뷰 및 슬롯에 대한 명시적 매핑을 요구하는 대신 게임이 다양한 리소스 보기를 만드는 설명자 힙을 제공합니다. 이 체계는 GPU가 하드웨어 네이티브 리소스 설명(설명자)을 메모리 앞에 직접 쓰는 메커니즘을 제공합니다. 파이프라인에서 특정 그리기 호출에 사용할 리소스를 선언하기 위해 게임은 전체 설명자 힙의 하위 범위를 나타내는 하나 이상의 설명자 테이블을 지정합니다. 설명자 힙이 이미 적절한 하드웨어별 설명자 데이터로 채워졌으므로 설명자 테이블을 변경하는 것은 매우 저렴한 작업입니다.
설명자 힙 및 테이블에서 제공하는 향상된 성능 외에도 Direct3D 12를 사용하면 리소스를 셰이더에서 동적으로 인덱싱할 수 있으므로 전례 없는 유연성을 제공하고 새로운 렌더링 기술을 잠금 해제할 수 있습니다. 예를 들어 최신 지연 렌더링 엔진은 일반적으로 어떤 종류의 재질 또는 개체 식별자를 중간 g 버퍼로 인코딩합니다. Direct3D 11에서 이러한 엔진은 너무 많은 재질을 사용하지 않도록 주의해야 합니다. 하나의 g-버퍼에 너무 많이 포함하면 최종 렌더링 패스 속도가 크게 느려질 수 있으므로 주의해야 합니다. 동적으로 인덱싱 가능한 리소스를 사용하면 1,000개의 재질이 있는 장면을 10개만 있는 장면만큼 빠르게 마무리할 수 있습니다.
설명자 힙 및 테이블에 대한 자세한 내용은 리소스 바인딩및 Direct3D 11 바인딩 모델의차이점을 참조하세요.
Direct3D 11에서 포팅
Direct3D 11에서 포팅은 Direct3D 11에서 Direct3D 12 포팅에 설명된 관련 프로세스입니다. 또한 Direct3D 11, Direct3D 10 및 Direct2D 옵션 범위를 참조하세요.
관련 항목
-
Direct3D 12 이해