ID3D11Device
인터페이스는 DX를 사용할 때 접할 수 있는 대표적인 COM 객체이며, 추상화된 하드웨어를 나타낸다. 프로그래머는 응용 프로그램 단계에서 ID3D11Device
인터페이스를 통해 간접적으로 하드웨어(그래픽 카드)를 제어할 수 있게 된다. ID3D11Device
에 조금 더 친숙해질 수 있도록 관련 팁들에 대해서 알아 보자.
1. COM 객체 생성과 복사
COM 객체는 new
, delete
와 같은 표준 C++ 키워드를 사용해서 객체를 생성하거나 제거하면 안 된다. COM 객체를 위한 전용 함수를 사용해야 하고, 조금 더 편리하게 사용하기 위해 COM 객체를 위한 스마트 포인터인 ComPtr
을 사용할 수 있다.
ID3D11Device
는 DX의 대표적인 COM 객체다. ID3D11Device
객체를 생성한다는 것은 응용 프로그램에서 렌더링 작업을 부탁하게 될 그래픽 카드라는 하드웨어에 대한 접근 권한을 얻는 것과 같다고 볼 수도 있다. 여기서 알 수 있는 부분은 ID3D11Device
객체 생성은 응용 프로그램 단계에서 성공과 실패를 결정할 수 없다는 것이다. ID3D11Device
객체의 생성 작업 자체가 하드웨어에서 현재 응용 프로그램에서 사용하는 그래픽스 라이브러리가 지원 가능한지 아닌지 등을 판단하는 작업이기 때문이다.
안정적인 프로그램을 제공하기 위해선 일반적으로 응용 프로그램 외부에 있는 어떤 요소와 상호 작용을 하는 경우에는 그 작업의 실패 가능성을 항상 염두해 두어야 한다. ID3D11Device
객체 생성 작업 역시 마찬가지의 작업이라고 볼 수 있다. 그래서 ID3D11Device
객체 생성 함수를 호출하여 객체가 정상적으로 생성되었는지 확인을 하고, 그 뒤에 실제로 사용할 클래스의 멤버 변수나 전역 변수 등으로 복사하여 사용하는 것을 권장한다.
2. ID3D11Device 생성 함수
ID3D11Device
객체를 생성하기 위한 대표적인 함수는 D3D11CreateDevice
함수라고 할 수 있다.(경우에 따라 스왑 체인을 함께 만들어 주는 D3D11CreateDeviceAndSwapChain
을 사용할 수도 있다.)
// https://learn.microsoft.com/ko-kr/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice
HRESULT D3D11CreateDevice(
[in, optional] IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
[in, optional] const D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
[out, optional] ID3D11Device **ppDevice,
[out, optional] D3D_FEATURE_LEVEL *pFeatureLevel,
[out, optional] ID3D11DeviceContext **ppImmediateContext
);
함수의 인자에 대해서 하나씩 용도를 확인하면 조금 더 친숙하게 느껴질 것이다.
2.1 IDXGIAdapter* pAdapter
인자의 이름을 보고 ID3D11Device
의 역할을 생각해보면 그 의미를 어렵지 않게 유추할 수 있다. 하드웨어에 대한 인터페이스를 만들 때 필요한 디바이스 어댑터를 입력해주는 것이다. optional
표시가 된 인자들은 0이나 NULL을 입력해주면 기본값을 사용하게 되는데, 디바이스를 생성할 때에는 NULL을 입력하여 디폴트 디바이스 어댑터를 선택하도록 만들어 주면 된다.
IDXGI
인터페이스는 마이크로소프트에서 제공하는 다양한 버전의 DirectX가 공통적으로 사용할 수 있는 저수준 제어 관련 인터페이스다.IDXGIAdapter
는 응용 프로그램과 하드웨어를 연결할 어댑터와 관련된 객체라고 생각하면 된다.
2.2 D3D_DRIVER_TYPE DriverType
DirectX11 3D에서 어떤 종류의 드라이버를 사용할지 결정하는 인자이다. 그래픽 카드 호환성 문제로 디바이스 생성에 실패하는 경우에는 소프트웨어 래스터라이저를 사용하는 것도 한 가지 방법이 될 수 있다.
// 그래픽 카드 드라이버 사용
D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE
// 소프트웨어 래스터라이저 WARP 드라이버 사용
D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_WARP;
2.3 HMODULE Software
앞에서 살펴 본 DriverType
과 관련된 인자다. 드라이버 타입을 하드웨어로 결정했다면 이 값에 NULL을 사용하면 된다. 하지만 D3D_DRIVER_TYPE_SOFTWARE
를 사용한 경우에는 NULL이 아닌 소프트웨어 래스터라이저의 핸들을 입력해주어야 한다. 대부분 NULL을 입력하면 될 것이다.
2.4 UINT Flags
디바이스 생성을 하면서 설정할 수 있는 옵션에 대한 인자다. 자세한 내용은 https://learn.microsoft.com/ko-kr/windows/win32/api/d3d11/ne-d3d11-d3d11_create_device_flag
문서를 참고하면 된다.
2.5 const D3D_FEATURE_LEVEL* pFeatureLevel
지금 사용하고 있는 DX의 버전은 11이지만 어떤 하드웨어에서는 DX11을 지원하지 않을 수도 있을 것이다. 이런 경우를 대비해 디바이스를 생성하는 과정에서 DX의 버전(= FeatureLevel
)을 여러 개 설정할 수 있게 하는 옵션이라고 보면 된다. 배열 형식으로 제공해야 하며, 버전이 높은 순서대로 배열의 원소를 입력해야 한다.
const D3D_FEATURE_LEVEL featureLevels[2] = {
D3D_FEATURE_LEVEL_11_0, // 더 높은 버전이 먼저 오도록 설정
D3D_FEATURE_LEVEL_9_3
};
2.6 UINT FeatureLevels
앞에서 본 pFeatureLevel
배열의 길이를 의미한다.
2.7 UINT SDKVersion
우리는 DX11을 사용하고 있기 때문에 D3D11_SDK_VERSION
을 고정해서 사용하면 된다.
2.8 ID3D11Device** ppDevice
함수 호출을 통해 생성된 디바이스에 대한 ID3D11Device
객체가 리턴된다.
2.9 D3D_FEATURE_LEVEL* pFeatureLevel
앞에서 지정한 DX의 버전들 중에서 설정에 성공한 버전이 리턴된다.
2.10 ID3D11DeviceContext** ppImmediateContext
디바이스 컨텍스트 객체가 리턴된다. 여기에서 리턴되는 디바이스 컨텍스트는 인자의 이름처럼 ImmediateContext
인데, 명령을 내리자마자 즉시 수행을 하는 유형의 디바이스 컨텍스트라고 보면 된다. 반대로 DeferredContext
의 경우에는 해당 디바이스에서 수행해야 하는 작업의 목록을 관리하고 있다가 수행 요청을 보내야 작업을 수행한다.(주로 멀티스레드 환경과 같이 최적화가 필요한 부분에서 사용하며, 별도의 생성 함수가 존재한다.)
'그래픽스 > DirectX11' 카테고리의 다른 글
RenderTargetView의 의미 (0) | 2024.04.19 |
---|---|
DXGI_SWAP_CHAIN_DESC에 관하여 (1) | 2024.04.19 |
DirectX에서의 COM(Component Object Model) (0) | 2024.04.15 |
DirectX 11 도형 출력(버텍스 버퍼, 버텍스 쉐이더, 픽셀 쉐이더 설정) (0) | 2024.04.12 |
DirectX 11 초기 설정(Device, DeviceContext, SwapChain) (0) | 2024.04.12 |